]> rtime.felk.cvut.cz Git - can-eth-gw-linux.git/commitdiff
Merge branch 'akpm' (Andrew's patch-bomb)
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 13 Dec 2012 21:11:15 +0000 (13:11 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 13 Dec 2012 21:11:15 +0000 (13:11 -0800)
Merge misc VM changes from Andrew Morton:
 "The rest of most-of-MM.  The other MM bits await a slab merge.

  This patch includes the addition of a huge zero_page.  Not a
  performance boost but it an save large amounts of physical memory in
  some situations.

  Also a bunch of Fujitsu engineers are working on memory hotplug.
  Which, as it turns out, was badly broken.  About half of their patches
  are included here; the remainder are 3.8 material."

However, this merge disables CONFIG_MOVABLE_NODE, which was totally
broken.  We don't add new features with "default y", nor do we add
Kconfig questions that are incomprehensible to most people without any
help text.  Does the feature even make sense without compaction or
memory hotplug?

* akpm: (54 commits)
  mm/bootmem.c: remove unused wrapper function reserve_bootmem_generic()
  mm/memory.c: remove unused code from do_wp_page()
  asm-generic, mm: pgtable: consolidate zero page helpers
  mm/hugetlb.c: fix warning on freeing hwpoisoned hugepage
  hwpoison, hugetlbfs: fix RSS-counter warning
  hwpoison, hugetlbfs: fix "bad pmd" warning in unmapping hwpoisoned hugepage
  mm: protect against concurrent vma expansion
  memcg: do not check for mm in __mem_cgroup_count_vm_event
  tmpfs: support SEEK_DATA and SEEK_HOLE (reprise)
  mm: provide more accurate estimation of pages occupied by memmap
  fs/buffer.c: remove redundant initialization in alloc_page_buffers()
  fs/buffer.c: do not inline exported function
  writeback: fix a typo in comment
  mm: introduce new field "managed_pages" to struct zone
  mm, oom: remove statically defined arch functions of same name
  mm, oom: remove redundant sleep in pagefault oom handler
  mm, oom: cleanup pagefault oom handler
  memory_hotplug: allow online/offline memory to result movable node
  numa: add CONFIG_MOVABLE_NODE for movable-dedicated node
  mm, memcg: avoid unnecessary function call when memcg is disabled
  ...

2683 files changed:
Documentation/ABI/obsolete/sysfs-driver-hid-roccat-koneplus
Documentation/ABI/obsolete/sysfs-driver-hid-roccat-kovaplus [new file with mode: 0644]
Documentation/ABI/obsolete/sysfs-driver-hid-roccat-pyra [new file with mode: 0644]
Documentation/ABI/testing/dev-kmsg
Documentation/ABI/testing/sysfs-bus-mdio [new file with mode: 0644]
Documentation/ABI/testing/sysfs-bus-pci
Documentation/ABI/testing/sysfs-class-net-batman-adv
Documentation/ABI/testing/sysfs-class-net-grcan [new file with mode: 0644]
Documentation/ABI/testing/sysfs-class-net-mesh
Documentation/ABI/testing/sysfs-devices-power
Documentation/ABI/testing/sysfs-driver-hid-roccat-isku
Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus
Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus
Documentation/ABI/testing/sysfs-driver-hid-roccat-lua [new file with mode: 0644]
Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra
Documentation/ABI/testing/sysfs-driver-hid-roccat-savu
Documentation/ABI/testing/sysfs-driver-ppi
Documentation/ABI/testing/sysfs-profiling
Documentation/DocBook/writing-an-alsa-driver.tmpl
Documentation/HOWTO
Documentation/PCI/pci-iov-howto.txt
Documentation/accounting/getdelays.c
Documentation/bus-devices/ti-gpmc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/exynos/power_domain.txt
Documentation/devicetree/bindings/arm/fsl.txt
Documentation/devicetree/bindings/ata/exynos-sata-phy.txt [new file with mode: 0644]
Documentation/devicetree/bindings/ata/exynos-sata.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/imx25-clock.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/zynq-7000.txt [new file with mode: 0644]
Documentation/devicetree/bindings/drm/exynos/hdmi.txt [new file with mode: 0644]
Documentation/devicetree/bindings/drm/exynos/hdmiddc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/drm/exynos/hdmiphy.txt [new file with mode: 0644]
Documentation/devicetree/bindings/drm/exynos/mixer.txt [new file with mode: 0644]
Documentation/devicetree/bindings/gpio/gpio-poweroff.txt [new file with mode: 0644]
Documentation/devicetree/bindings/hwmon/vexpress.txt [new file with mode: 0644]
Documentation/devicetree/bindings/input/touchscreen/bu21013.txt [new file with mode: 0644]
Documentation/devicetree/bindings/media/s5p-mfc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/misc/atmel-ssc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/net/can/grcan.txt [new file with mode: 0644]
Documentation/devicetree/bindings/net/cdns-emac.txt [new file with mode: 0644]
Documentation/devicetree/bindings/net/cpsw.txt
Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt
Documentation/devicetree/bindings/regulator/gpio-regulator.txt [new file with mode: 0644]
Documentation/devicetree/bindings/regulator/max8925-regulator.txt [new file with mode: 0644]
Documentation/devicetree/bindings/regulator/max8997-regulator.txt [new file with mode: 0644]
Documentation/devicetree/bindings/regulator/vexpress.txt [new file with mode: 0644]
Documentation/devicetree/bindings/rtc/nvidia,tegra20-rtc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/ak4104.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/atmel-at91sam9g20ek-wm8731-audio.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/cs4271.txt
Documentation/devicetree/bindings/sound/omap-abe-twl6040.txt
Documentation/devicetree/bindings/timer/nvidia,tegra20-timer.txt [new file with mode: 0644]
Documentation/devicetree/bindings/timer/nvidia,tegra30-timer.txt [new file with mode: 0644]
Documentation/devicetree/bindings/usb/ehci-orion.txt [new file with mode: 0644]
Documentation/devicetree/bindings/vendor-prefixes.txt
Documentation/devicetree/bindings/watchdog/atmel-wdt.txt [new file with mode: 0644]
Documentation/dma-buf-sharing.txt
Documentation/dontdiff
Documentation/fault-injection/notifier-error-inject.txt
Documentation/hid/uhid.txt
Documentation/hwmon/pmbus
Documentation/hwmon/vexpress [new file with mode: 0644]
Documentation/input/alps.txt
Documentation/input/event-codes.txt
Documentation/kbuild/modules.txt
Documentation/kernel-doc-nano-HOWTO.txt
Documentation/kernel-parameters.txt
Documentation/misc-devices/mei/mei-amt-version.c
Documentation/networking/batman-adv.txt
Documentation/networking/ip-sysctl.txt
Documentation/networking/packet_mmap.txt
Documentation/networking/stmmac.txt
Documentation/sound/alsa/ALSA-Configuration.txt
Documentation/video4linux/bttv/Cards
Documentation/video4linux/bttv/Sound-FAQ
Documentation/vm/frontswap.txt
MAINTAINERS
README
arch/alpha/include/asm/mmzone.h
arch/alpha/include/asm/socket.h
arch/alpha/kernel/pci_iommu.c
arch/arm/Kconfig
arch/arm/Kconfig.debug
arch/arm/Makefile
arch/arm/boot/dts/Makefile
arch/arm/boot/dts/am335x-bone.dts
arch/arm/boot/dts/am335x-evm.dts
arch/arm/boot/dts/am33xx.dtsi
arch/arm/boot/dts/at91sam9260.dtsi
arch/arm/boot/dts/at91sam9263.dtsi
arch/arm/boot/dts/at91sam9g20ek_common.dtsi
arch/arm/boot/dts/at91sam9g45.dtsi
arch/arm/boot/dts/at91sam9x5.dtsi
arch/arm/boot/dts/ccu9540.dts [new file with mode: 0644]
arch/arm/boot/dts/cros5250-common.dtsi [new file with mode: 0644]
arch/arm/boot/dts/dbx5x0.dtsi
arch/arm/boot/dts/dove-cubox.dts
arch/arm/boot/dts/dove.dtsi
arch/arm/boot/dts/evk-pro3.dts
arch/arm/boot/dts/exynos4.dtsi
arch/arm/boot/dts/exynos4210-origen.dts
arch/arm/boot/dts/exynos4210-pinctrl.dtsi
arch/arm/boot/dts/exynos4210-smdkv310.dts
arch/arm/boot/dts/exynos4210-trats.dts
arch/arm/boot/dts/exynos4210.dtsi
arch/arm/boot/dts/exynos4212.dtsi [new file with mode: 0644]
arch/arm/boot/dts/exynos4412-smdk4412.dts [new file with mode: 0644]
arch/arm/boot/dts/exynos4412.dtsi [new file with mode: 0644]
arch/arm/boot/dts/exynos4x12-pinctrl.dtsi [new file with mode: 0644]
arch/arm/boot/dts/exynos4x12.dtsi [new file with mode: 0644]
arch/arm/boot/dts/exynos5250-smdk5250.dts
arch/arm/boot/dts/exynos5250-snow.dts [new file with mode: 0644]
arch/arm/boot/dts/exynos5250.dtsi
arch/arm/boot/dts/href.dtsi [new file with mode: 0644]
arch/arm/boot/dts/hrefprev60.dts [new file with mode: 0644]
arch/arm/boot/dts/hrefv60plus.dts
arch/arm/boot/dts/imx23-olinuxino.dts
arch/arm/boot/dts/imx23.dtsi
arch/arm/boot/dts/imx25-karo-tx25.dts [new file with mode: 0644]
arch/arm/boot/dts/imx25.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx27-apf27.dts [new file with mode: 0644]
arch/arm/boot/dts/imx27.dtsi
arch/arm/boot/dts/imx28-apf28.dts [new file with mode: 0644]
arch/arm/boot/dts/imx28-apf28dev.dts [new file with mode: 0644]
arch/arm/boot/dts/imx28-cfa10036.dts
arch/arm/boot/dts/imx28-cfa10049.dts
arch/arm/boot/dts/imx28-evk.dts
arch/arm/boot/dts/imx28-sps1.dts [new file with mode: 0644]
arch/arm/boot/dts/imx28.dtsi
arch/arm/boot/dts/imx51.dtsi
arch/arm/boot/dts/imx53-qsb.dts
arch/arm/boot/dts/imx53.dtsi
arch/arm/boot/dts/imx6q-sabreauto.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6q-sabresd.dts
arch/arm/boot/dts/imx6q.dtsi
arch/arm/boot/dts/kirkwood-6281.dtsi [new file with mode: 0644]
arch/arm/boot/dts/kirkwood-6282.dtsi [new file with mode: 0644]
arch/arm/boot/dts/kirkwood-98dx4122.dtsi [new file with mode: 0644]
arch/arm/boot/dts/kirkwood-dnskw.dtsi
arch/arm/boot/dts/kirkwood-dockstar.dts
arch/arm/boot/dts/kirkwood-dreamplug.dts
arch/arm/boot/dts/kirkwood-goflexnet.dts
arch/arm/boot/dts/kirkwood-ib62x0.dts
arch/arm/boot/dts/kirkwood-iconnect.dts
arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts
arch/arm/boot/dts/kirkwood-km_kirkwood.dts
arch/arm/boot/dts/kirkwood-lsxl.dtsi
arch/arm/boot/dts/kirkwood-mplcec4.dts
arch/arm/boot/dts/kirkwood-openblocks_a6.dts
arch/arm/boot/dts/kirkwood-ts219-6281.dts
arch/arm/boot/dts/kirkwood-ts219-6282.dts
arch/arm/boot/dts/kirkwood.dtsi
arch/arm/boot/dts/lpc32xx.dtsi
arch/arm/boot/dts/snowball.dts
arch/arm/boot/dts/stuib.dtsi [new file with mode: 0644]
arch/arm/boot/dts/tegra20-harmony.dts
arch/arm/boot/dts/tegra20-plutux.dts
arch/arm/boot/dts/tegra20-seaboard.dts
arch/arm/boot/dts/tegra20-tamonten.dtsi
arch/arm/boot/dts/tegra20-tec.dts
arch/arm/boot/dts/tegra20-trimslice.dts
arch/arm/boot/dts/tegra20-ventana.dts
arch/arm/boot/dts/tegra20-whistler.dts
arch/arm/boot/dts/tegra20.dtsi
arch/arm/boot/dts/tegra30-cardhu-a02.dts
arch/arm/boot/dts/tegra30-cardhu-a04.dts
arch/arm/boot/dts/tegra30-cardhu.dtsi
arch/arm/boot/dts/tegra30.dtsi
arch/arm/boot/dts/u9540.dts [new file with mode: 0644]
arch/arm/boot/dts/zynq-7000.dtsi [new file with mode: 0644]
arch/arm/boot/dts/zynq-ep107.dts [deleted file]
arch/arm/boot/dts/zynq-zc702.dts [new file with mode: 0644]
arch/arm/configs/marzen_defconfig
arch/arm/configs/mxs_defconfig
arch/arm/configs/omap2plus_defconfig
arch/arm/configs/u8500_defconfig
arch/arm/include/debug/imx.S
arch/arm/include/debug/tegra.S [new file with mode: 0644]
arch/arm/include/debug/zynq.S [moved from arch/arm/mach-zynq/include/mach/debug-macro.S with 61% similarity]
arch/arm/kernel/kprobes-test.c
arch/arm/mach-at91/Kconfig
arch/arm/mach-at91/at91rm9200.c
arch/arm/mach-at91/at91rm9200_devices.c
arch/arm/mach-at91/at91sam9260.c
arch/arm/mach-at91/at91sam9260_devices.c
arch/arm/mach-at91/at91sam9261.c
arch/arm/mach-at91/at91sam9261_devices.c
arch/arm/mach-at91/at91sam9263.c
arch/arm/mach-at91/at91sam9263_devices.c
arch/arm/mach-at91/at91sam9g45.c
arch/arm/mach-at91/at91sam9g45_devices.c
arch/arm/mach-at91/at91sam9rl.c
arch/arm/mach-at91/at91sam9rl_devices.c
arch/arm/mach-at91/at91sam9x5.c
arch/arm/mach-at91/board-csb337.c
arch/arm/mach-at91/board-sam9g20ek.c
arch/arm/mach-at91/include/mach/at91rm9200_emac.h [deleted file]
arch/arm/mach-davinci/Makefile.boot
arch/arm/mach-davinci/board-da850-evm.c
arch/arm/mach-exynos/Kconfig
arch/arm/mach-exynos/Makefile
arch/arm/mach-exynos/clock-exynos4.c
arch/arm/mach-exynos/clock-exynos5.c
arch/arm/mach-exynos/common.c
arch/arm/mach-exynos/cpuidle.c
arch/arm/mach-exynos/dev-drm.c [deleted file]
arch/arm/mach-exynos/hotplug.c
arch/arm/mach-exynos/include/mach/irqs.h
arch/arm/mach-exynos/include/mach/map.h
arch/arm/mach-exynos/mach-armlex4210.c
arch/arm/mach-exynos/mach-exynos4-dt.c
arch/arm/mach-exynos/mach-exynos5-dt.c
arch/arm/mach-exynos/mach-nuri.c
arch/arm/mach-exynos/mach-origen.c
arch/arm/mach-exynos/mach-smdk4x12.c
arch/arm/mach-exynos/mach-smdkv310.c
arch/arm/mach-exynos/mach-universal_c210.c
arch/arm/mach-exynos/pm.c
arch/arm/mach-exynos/pm_domains.c
arch/arm/mach-imx/Kconfig
arch/arm/mach-imx/Makefile
arch/arm/mach-imx/clk-imx25.c
arch/arm/mach-imx/clk-imx6q.c
arch/arm/mach-imx/common.h
arch/arm/mach-imx/imx25-dt.c [new file with mode: 0644]
arch/arm/mach-imx/lluart.c
arch/arm/mach-imx/mach-imx6q.c
arch/arm/mach-imx/mx6q.h
arch/arm/mach-kirkwood/Kconfig
arch/arm/mach-kirkwood/board-dnskw.c
arch/arm/mach-kirkwood/board-dockstar.c
arch/arm/mach-kirkwood/board-dreamplug.c
arch/arm/mach-kirkwood/board-goflexnet.c
arch/arm/mach-kirkwood/board-ib62x0.c
arch/arm/mach-kirkwood/board-iconnect.c
arch/arm/mach-kirkwood/board-iomega_ix2_200.c
arch/arm/mach-kirkwood/board-km_kirkwood.c
arch/arm/mach-kirkwood/board-lsxl.c
arch/arm/mach-kirkwood/board-mplcec4.c
arch/arm/mach-kirkwood/board-ns2.c
arch/arm/mach-kirkwood/board-nsa310.c
arch/arm/mach-kirkwood/board-openblocks_a6.c
arch/arm/mach-kirkwood/board-ts219.c
arch/arm/mach-kirkwood/board-usi_topkick.c
arch/arm/mach-mxs/mach-mxs.c
arch/arm/mach-mxs/timer.c
arch/arm/mach-netx/xc.c
arch/arm/mach-nomadik/Kconfig
arch/arm/mach-nomadik/board-nhk8815.c
arch/arm/mach-nomadik/include/mach/irqs.h
arch/arm/mach-omap1/board-h2.c
arch/arm/mach-omap1/board-h3.c
arch/arm/mach-omap1/board-palmte.c
arch/arm/mach-omap1/board-palmtt.c
arch/arm/mach-omap1/board-palmz71.c
arch/arm/mach-omap1/board-sx1.c
arch/arm/mach-omap1/dma.c
arch/arm/mach-omap1/io.c
arch/arm/mach-omap1/lcd_dma.c
arch/arm/mach-omap1/mcbsp.c
arch/arm/mach-omap1/pm.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/board-3430sdp.c
arch/arm/mach-omap2/board-h4.c
arch/arm/mach-omap2/board-rx51-peripherals.c
arch/arm/mach-omap2/board-rx51.c
arch/arm/mach-omap2/cclock2420_data.c [new file with mode: 0644]
arch/arm/mach-omap2/cclock2430_data.c [new file with mode: 0644]
arch/arm/mach-omap2/cclock33xx_data.c [new file with mode: 0644]
arch/arm/mach-omap2/cclock3xxx_data.c [new file with mode: 0644]
arch/arm/mach-omap2/cclock44xx_data.c [new file with mode: 0644]
arch/arm/mach-omap2/clkt2xxx_apll.c
arch/arm/mach-omap2/clkt2xxx_dpll.c
arch/arm/mach-omap2/clkt2xxx_dpllcore.c
arch/arm/mach-omap2/clkt2xxx_osc.c
arch/arm/mach-omap2/clkt2xxx_sys.c
arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
arch/arm/mach-omap2/clkt34xx_dpll3m2.c
arch/arm/mach-omap2/clkt_clksel.c
arch/arm/mach-omap2/clkt_dpll.c
arch/arm/mach-omap2/clkt_iclk.c
arch/arm/mach-omap2/clock.c
arch/arm/mach-omap2/clock.h
arch/arm/mach-omap2/clock2420_data.c [deleted file]
arch/arm/mach-omap2/clock2430.c
arch/arm/mach-omap2/clock2430_data.c [deleted file]
arch/arm/mach-omap2/clock2xxx.c
arch/arm/mach-omap2/clock2xxx.h
arch/arm/mach-omap2/clock33xx_data.c [deleted file]
arch/arm/mach-omap2/clock34xx.c
arch/arm/mach-omap2/clock3517.c
arch/arm/mach-omap2/clock36xx.c
arch/arm/mach-omap2/clock36xx.h
arch/arm/mach-omap2/clock3xxx.c
arch/arm/mach-omap2/clock3xxx.h
arch/arm/mach-omap2/clock3xxx_data.c [deleted file]
arch/arm/mach-omap2/clock44xx_data.c [deleted file]
arch/arm/mach-omap2/clock_common_data.c
arch/arm/mach-omap2/clockdomain.c
arch/arm/mach-omap2/cm-regbits-24xx.h
arch/arm/mach-omap2/cm-regbits-34xx.h
arch/arm/mach-omap2/cm2xxx_3xxx.h
arch/arm/mach-omap2/control.h
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/dma.c
arch/arm/mach-omap2/dpll3xxx.c
arch/arm/mach-omap2/dpll44xx.c
arch/arm/mach-omap2/gpmc-nand.c
arch/arm/mach-omap2/gpmc-onenand.c
arch/arm/mach-omap2/gpmc-smc91x.c
arch/arm/mach-omap2/gpmc.c
arch/arm/mach-omap2/gpmc.h
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/mcbsp.c
arch/arm/mach-omap2/omap_device.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod.h
arch/arm/mach-omap2/omap_hwmod_2420_data.c
arch/arm/mach-omap2/omap_hwmod_2430_data.c
arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
arch/arm/mach-omap2/omap_hwmod_33xx_data.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/omap_opp_data.h
arch/arm/mach-omap2/omap_phy_internal.c
arch/arm/mach-omap2/omap_twl.c
arch/arm/mach-omap2/opp4xxx_data.c
arch/arm/mach-omap2/pm.c
arch/arm/mach-omap2/pm.h
arch/arm/mach-omap2/pm24xx.c
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/pm44xx.c
arch/arm/mach-omap2/prm-regbits-24xx.h
arch/arm/mach-omap2/prm-regbits-34xx.h
arch/arm/mach-omap2/prm.h
arch/arm/mach-omap2/prm2xxx.c
arch/arm/mach-omap2/prm2xxx.h
arch/arm/mach-omap2/prm2xxx_3xxx.h
arch/arm/mach-omap2/prm3xxx.c
arch/arm/mach-omap2/prm3xxx.h
arch/arm/mach-omap2/prm44xx.c
arch/arm/mach-omap2/prm44xx.h
arch/arm/mach-omap2/prm_common.c
arch/arm/mach-omap2/scrm44xx.h
arch/arm/mach-omap2/serial.c
arch/arm/mach-omap2/sr_device.c
arch/arm/mach-omap2/usb-tusb6010.c
arch/arm/mach-omap2/vc.c
arch/arm/mach-omap2/vc.h
arch/arm/mach-omap2/vc3xxx_data.c
arch/arm/mach-omap2/vc44xx_data.c
arch/arm/mach-omap2/voltage.h
arch/arm/mach-omap2/voltagedomains3xxx_data.c
arch/arm/mach-omap2/voltagedomains44xx_data.c
arch/arm/mach-omap2/vp.c
arch/arm/mach-omap2/vp.h
arch/arm/mach-omap2/vp3xxx_data.c
arch/arm/mach-omap2/vp44xx_data.c
arch/arm/mach-s3c24xx/include/mach/bast-map.h
arch/arm/mach-s3c24xx/include/mach/dma.h
arch/arm/mach-s3c24xx/include/mach/vr1000-map.h
arch/arm/mach-s3c24xx/mach-gta02.c
arch/arm/mach-s3c24xx/mach-h1940.c
arch/arm/mach-s3c24xx/mach-mini2440.c
arch/arm/mach-s3c24xx/mach-rx1950.c
arch/arm/mach-s3c24xx/pm.c
arch/arm/mach-s3c64xx/mach-crag6410.c
arch/arm/mach-s3c64xx/mach-smdk6410.c
arch/arm/mach-s5p64x0/mach-smdk6440.c
arch/arm/mach-s5p64x0/mach-smdk6450.c
arch/arm/mach-s5pc100/mach-smdkc100.c
arch/arm/mach-s5pv210/mach-smdkc110.c
arch/arm/mach-s5pv210/mach-smdkv210.c
arch/arm/mach-shmobile/Kconfig
arch/arm/mach-shmobile/board-ap4evb.c
arch/arm/mach-shmobile/board-armadillo800eva.c
arch/arm/mach-shmobile/board-mackerel.c
arch/arm/mach-shmobile/board-marzen.c
arch/arm/mach-tegra/Kconfig
arch/arm/mach-tegra/common.c
arch/arm/mach-tegra/include/mach/debug-macro.S [deleted file]
arch/arm/mach-tegra/include/mach/irqs.h [deleted file]
arch/arm/mach-tegra/include/mach/uncompress.h
arch/arm/mach-tegra/io.c
arch/arm/mach-tegra/iomap.h
arch/arm/mach-tegra/irammap.h
arch/arm/mach-tegra/pcie.c
arch/arm/mach-tegra/timer.c
arch/arm/mach-ux500/Kconfig
arch/arm/mach-ux500/board-mop500-audio.c
arch/arm/mach-ux500/board-mop500-pins.c
arch/arm/mach-ux500/board-mop500-sdi.c
arch/arm/mach-ux500/board-mop500-stuib.c
arch/arm/mach-ux500/board-mop500.c
arch/arm/mach-ux500/board-mop500.h
arch/arm/mach-ux500/cpu-db8500.c
arch/arm/mach-ux500/cpu.c
arch/arm/mach-ux500/devices-common.c
arch/arm/mach-ux500/devices-db8500.c
arch/arm/mach-ux500/devices-db8500.h
arch/arm/mach-ux500/include/mach/irqs.h
arch/arm/mach-ux500/include/mach/msp.h
arch/arm/mach-ux500/timer.c
arch/arm/mach-ux500/usb.c
arch/arm/mach-vexpress/reset.c [new file with mode: 0644]
arch/arm/mach-vt8500/Kconfig [new file with mode: 0644]
arch/arm/mach-vt8500/common.h
arch/arm/mach-vt8500/include/mach/entry-macro.S [deleted file]
arch/arm/mach-vt8500/irq.c
arch/arm/mach-vt8500/vt8500.c
arch/arm/mach-zynq/Kconfig [new file with mode: 0644]
arch/arm/mach-zynq/common.c
arch/arm/mach-zynq/common.h
arch/arm/mach-zynq/include/mach/hardware.h [deleted file]
arch/arm/mach-zynq/include/mach/irqs.h [deleted file]
arch/arm/mach-zynq/include/mach/timex.h [deleted file]
arch/arm/mach-zynq/include/mach/uart.h [deleted file]
arch/arm/mach-zynq/include/mach/uncompress.h [deleted file]
arch/arm/mach-zynq/include/mach/zynq_soc.h [deleted file]
arch/arm/mach-zynq/timer.c
arch/arm/net/bpf_jit_32.c
arch/arm/net/bpf_jit_32.h
arch/arm/plat-nomadik/Kconfig [deleted file]
arch/arm/plat-nomadik/Makefile [deleted file]
arch/arm/plat-omap/dma.c
arch/arm/plat-omap/include/plat-omap/dma-omap.h [deleted file]
arch/arm/plat-orion/irq.c
arch/arm/plat-s3c24xx/dma.c
arch/arm/plat-samsung/devs.c
arch/arm/plat-samsung/include/plat/devs.h
arch/arm/plat-samsung/include/plat/gpio-core.h
arch/arm/plat-samsung/include/plat/mfc.h
arch/arm/plat-samsung/include/plat/pm.h
arch/arm/plat-samsung/s5p-dev-mfc.c
arch/arm/plat-samsung/s5p-irq-gpioint.c
arch/avr32/Kconfig
arch/avr32/include/uapi/asm/socket.h
arch/blackfin/mach-bf609/Kconfig
arch/blackfin/mm/sram-alloc.c
arch/cris/include/arch-v10/arch/irq.h
arch/cris/include/arch-v32/arch/irq.h
arch/cris/include/asm/socket.h
arch/frv/include/uapi/asm/socket.h
arch/frv/mm/pgalloc.c
arch/h8300/include/asm/socket.h
arch/ia64/include/uapi/asm/socket.h
arch/ia64/kvm/kvm-ia64.c
arch/m32r/include/asm/socket.h
arch/m68k/include/uapi/asm/socket.h
arch/m68k/math-emu/fp_log.c
arch/mips/bcm47xx/nvram.c
arch/mips/bcm47xx/wgt634u.c
arch/mips/include/uapi/asm/socket.h
arch/mips/txx9/generic/pci.c
arch/mn10300/include/asm/io.h
arch/mn10300/include/uapi/asm/socket.h
arch/mn10300/kernel/asm-offsets.c
arch/mn10300/kernel/irq.c
arch/mn10300/kernel/mn10300-serial-low.S
arch/mn10300/kernel/mn10300-serial.c
arch/mn10300/kernel/mn10300-serial.h
arch/mn10300/kernel/smp.c
arch/mn10300/mm/fault.c
arch/mn10300/mm/pgtable.c
arch/mn10300/unit-asb2305/pci-iomap.c [new file with mode: 0644]
arch/mn10300/unit-asb2305/pci.c
arch/openrisc/Kconfig
arch/parisc/include/uapi/asm/socket.h
arch/powerpc/include/asm/oprofile_impl.h
arch/powerpc/include/asm/ppc-opcode.h
arch/powerpc/include/asm/pte-hash64-64k.h
arch/powerpc/include/asm/smu.h
arch/powerpc/include/uapi/asm/socket.h
arch/powerpc/kernel/legacy_serial.c
arch/powerpc/kernel/of_platform.c
arch/powerpc/kernel/signal_64.c
arch/powerpc/mm/slice.c
arch/powerpc/net/bpf_jit.h
arch/powerpc/net/bpf_jit_comp.c
arch/powerpc/platforms/52xx/mpc52xx_gpt.c
arch/powerpc/platforms/cell/iommu.c
arch/powerpc/platforms/cell/spider-pic.c
arch/powerpc/platforms/powermac/pic.c
arch/s390/include/uapi/asm/socket.h
arch/sh/boards/board-espt.c
arch/sparc/include/uapi/asm/socket.h
arch/sparc/net/bpf_jit_comp.c
arch/x86/Kconfig
arch/x86/boot/.gitignore
arch/x86/boot/compressed/eboot.c
arch/x86/include/asm/bootparam.h
arch/x86/include/asm/numachip/numachip.h [new file with mode: 0644]
arch/x86/include/asm/pci.h
arch/x86/kernel/apic/apic_numachip.c
arch/x86/kernel/cpu/mtrr/main.c
arch/x86/kernel/setup.c
arch/x86/mm/pgtable.c
arch/x86/net/bpf_jit_comp.c
arch/x86/pci/Makefile
arch/x86/pci/acpi.c
arch/x86/pci/common.c
arch/x86/pci/numachip.c [new file with mode: 0644]
arch/xtensa/include/uapi/asm/socket.h
drivers/acpi/acpica/dsopcode.c
drivers/acpi/pci_bind.c
drivers/acpi/pci_irq.c
drivers/acpi/pci_root.c
drivers/atm/solos-pci.c
drivers/bcma/bcma_private.h
drivers/bcma/driver_chipcommon.c
drivers/bcma/driver_chipcommon_nflash.c
drivers/bcma/driver_chipcommon_pmu.c
drivers/bcma/driver_chipcommon_sflash.c
drivers/bcma/driver_mips.c
drivers/bcma/driver_pci_host.c
drivers/bcma/host_pci.c
drivers/bcma/main.c
drivers/bcma/sprom.c
drivers/bluetooth/btmrvl_sdio.c
drivers/bluetooth/btusb.c
drivers/char/hw_random/Kconfig
drivers/char/ipmi/ipmi_msghandler.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/ppdev.c
drivers/clk/Makefile
drivers/clk/clk-zynq.c [new file with mode: 0644]
drivers/clk/ux500/u8500_clk.c
drivers/clocksource/Kconfig
drivers/clocksource/Makefile
drivers/clocksource/nomadik-mtu.c [moved from arch/arm/plat-nomadik/timer.c with 93% similarity]
drivers/crypto/omap-aes.c
drivers/crypto/omap-sham.c
drivers/crypto/ux500/cryp/cryp_core.c
drivers/dma/ioat/dca.c
drivers/dma/omap-dma.c
drivers/dma/ste_dma40.c
drivers/dma/ste_dma40_ll.c
drivers/eisa/eisa.ids
drivers/firewire/init_ohci1394_dma.c
drivers/firewire/net.c
drivers/firewire/ohci.c
drivers/firewire/sbp2.c
drivers/gpio/Kconfig
drivers/gpio/gpio-samsung.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/radeon_ring.c
drivers/gpu/drm/radeon/si.c
drivers/hid/Kconfig
drivers/hid/Makefile
drivers/hid/hid-apple.c
drivers/hid/hid-core.c
drivers/hid/hid-icade.c [new file with mode: 0644]
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-multitouch.c
drivers/hid/hid-roccat-isku.c
drivers/hid/hid-roccat-isku.h
drivers/hid/hid-roccat-koneplus.c
drivers/hid/hid-roccat-koneplus.h
drivers/hid/hid-roccat-kovaplus.c
drivers/hid/hid-roccat-kovaplus.h
drivers/hid/hid-roccat-lua.c [new file with mode: 0644]
drivers/hid/hid-roccat-lua.h [new file with mode: 0644]
drivers/hid/hid-roccat-pyra.c
drivers/hid/hid-roccat-pyra.h
drivers/hid/hid-roccat-savu.c
drivers/hid/hid-sensor-hub.c
drivers/hid/hidraw.c
drivers/hid/i2c-hid/Kconfig [new file with mode: 0644]
drivers/hid/i2c-hid/Makefile [new file with mode: 0644]
drivers/hid/i2c-hid/i2c-hid.c [new file with mode: 0644]
drivers/hid/usbhid/hid-quirks.c
drivers/hid/usbhid/hiddev.c
drivers/hwmon/Kconfig
drivers/hwmon/Makefile
drivers/hwmon/vexpress.c [new file with mode: 0644]
drivers/i2c/busses/i2c-nuc900.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/input/input-mt.c
drivers/input/keyboard/Kconfig
drivers/input/misc/Kconfig
drivers/input/misc/Makefile
drivers/input/misc/arizona-haptics.c [new file with mode: 0644]
drivers/isdn/hardware/mISDN/hfcpci.c
drivers/isdn/hardware/mISDN/mISDNisar.c
drivers/isdn/hisax/amd7930_fn.c
drivers/isdn/hisax/callc.c
drivers/isdn/hisax/hfc_pci.c
drivers/isdn/hisax/hfc_sx.c
drivers/isdn/hisax/isar.c
drivers/isdn/mISDN/l1oip_core.c
drivers/isdn/mISDN/tei.c
drivers/isdn/pcbit/layer2.c
drivers/md/md.c
drivers/md/persistent-data/dm-block-manager.c
drivers/md/persistent-data/dm-btree.h
drivers/md/raid5.c
drivers/media/dvb-frontends/drxk_hard.c
drivers/media/platform/mx2_emmaprp.c
drivers/media/platform/omap/omap_vout.c
drivers/media/platform/omap/omap_vout_vrfb.c
drivers/media/platform/omap3isp/ispstat.h
drivers/media/platform/soc_camera/omap1_camera.c
drivers/message/i2o/README.ioctl
drivers/message/i2o/i2o_block.c
drivers/message/i2o/i2o_config.c
drivers/mfd/Kconfig
drivers/mfd/ab8500-core.c
drivers/mfd/arizona-core.c
drivers/mfd/db8500-prcmu.c
drivers/mfd/max8997.c
drivers/mfd/tps6586x.c
drivers/mfd/wm5102-tables.c
drivers/mfd/wm8994-core.c
drivers/misc/atmel-ssc.c
drivers/mmc/host/Kconfig
drivers/mtd/maps/plat-ram.c
drivers/mtd/nand/Kconfig
drivers/mtd/nand/omap2.c
drivers/mtd/nand/s3c2410.c
drivers/mtd/onenand/omap2.c
drivers/net/arcnet/com20020-pci.c
drivers/net/bonding/bond_alb.c
drivers/net/bonding/bond_alb.h
drivers/net/bonding/bond_debugfs.c
drivers/net/bonding/bond_main.c
drivers/net/bonding/bonding.h
drivers/net/can/Kconfig
drivers/net/can/Makefile
drivers/net/can/at91_can.c
drivers/net/can/bfin_can.c
drivers/net/can/c_can/c_can.c
drivers/net/can/c_can/c_can.h
drivers/net/can/c_can/c_can_pci.c
drivers/net/can/c_can/c_can_platform.c
drivers/net/can/cc770/cc770_isa.c
drivers/net/can/cc770/cc770_platform.c
drivers/net/can/dev.c
drivers/net/can/flexcan.c
drivers/net/can/grcan.c [new file with mode: 0644]
drivers/net/can/janz-ican3.c
drivers/net/can/mcp251x.c
drivers/net/can/mscan/mpc5xxx_can.c
drivers/net/can/mscan/mscan.c
drivers/net/can/mscan/mscan.h
drivers/net/can/pch_can.c
drivers/net/can/sja1000/Kconfig
drivers/net/can/sja1000/ems_pci.c
drivers/net/can/sja1000/ems_pcmcia.c
drivers/net/can/sja1000/kvaser_pci.c
drivers/net/can/sja1000/peak_pci.c
drivers/net/can/sja1000/peak_pcmcia.c
drivers/net/can/sja1000/plx_pci.c
drivers/net/can/sja1000/sja1000.c
drivers/net/can/sja1000/sja1000.h
drivers/net/can/sja1000/sja1000_isa.c
drivers/net/can/sja1000/sja1000_of_platform.c
drivers/net/can/sja1000/sja1000_platform.c
drivers/net/can/sja1000/tscan1.c
drivers/net/can/softing/softing_cs.c
drivers/net/can/softing/softing_main.c
drivers/net/can/ti_hecc.c
drivers/net/can/usb/Kconfig
drivers/net/can/usb/Makefile
drivers/net/can/usb/ems_usb.c
drivers/net/can/usb/esd_usb2.c
drivers/net/can/usb/kvaser_usb.c [new file with mode: 0644]
drivers/net/can/usb/peak_usb/pcan_usb_core.c
drivers/net/can/usb/peak_usb/pcan_usb_core.h
drivers/net/dsa/Kconfig
drivers/net/ethernet/3com/3c509.c
drivers/net/ethernet/3com/3c59x.c
drivers/net/ethernet/3com/Kconfig
drivers/net/ethernet/3com/typhoon.c
drivers/net/ethernet/8390/ax88796.c
drivers/net/ethernet/8390/etherh.c
drivers/net/ethernet/8390/hydra.c
drivers/net/ethernet/8390/ne2k-pci.c
drivers/net/ethernet/8390/ne3210.c
drivers/net/ethernet/8390/zorro8390.c
drivers/net/ethernet/adaptec/starfire.c
drivers/net/ethernet/adi/Kconfig
drivers/net/ethernet/adi/bfin_mac.c
drivers/net/ethernet/adi/bfin_mac.h
drivers/net/ethernet/aeroflex/greth.c
drivers/net/ethernet/alteon/acenic.c
drivers/net/ethernet/amd/a2065.c
drivers/net/ethernet/amd/am79c961a.c
drivers/net/ethernet/amd/amd8111e.c
drivers/net/ethernet/amd/ariadne.c
drivers/net/ethernet/amd/au1000_eth.c
drivers/net/ethernet/amd/declance.c
drivers/net/ethernet/amd/depca.c
drivers/net/ethernet/amd/hplance.c
drivers/net/ethernet/amd/pcnet32.c
drivers/net/ethernet/amd/sunlance.c
drivers/net/ethernet/apple/bmac.c
drivers/net/ethernet/apple/mace.c
drivers/net/ethernet/apple/macmace.c
drivers/net/ethernet/atheros/atl1c/atl1c_main.c
drivers/net/ethernet/atheros/atl1e/atl1e_main.c
drivers/net/ethernet/atheros/atl1e/atl1e_param.c
drivers/net/ethernet/atheros/atlx/atl1.c
drivers/net/ethernet/atheros/atlx/atl2.c
drivers/net/ethernet/broadcom/Kconfig
drivers/net/ethernet/broadcom/b44.c
drivers/net/ethernet/broadcom/bcm63xx_enet.c
drivers/net/ethernet/broadcom/bnx2.c
drivers/net/ethernet/broadcom/bnx2.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h
drivers/net/ethernet/broadcom/cnic.c
drivers/net/ethernet/broadcom/cnic.h
drivers/net/ethernet/broadcom/cnic_if.h
drivers/net/ethernet/broadcom/sb1250-mac.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/broadcom/tg3.h
drivers/net/ethernet/brocade/bna/bfa_ioc.c
drivers/net/ethernet/brocade/bna/bfi_enet.h
drivers/net/ethernet/brocade/bna/bna.h
drivers/net/ethernet/brocade/bna/bna_hw_defs.h
drivers/net/ethernet/brocade/bna/bna_tx_rx.c
drivers/net/ethernet/brocade/bna/bna_types.h
drivers/net/ethernet/brocade/bna/bnad.c
drivers/net/ethernet/brocade/bna/bnad.h
drivers/net/ethernet/brocade/bna/bnad_ethtool.c
drivers/net/ethernet/brocade/bna/cna.h
drivers/net/ethernet/cadence/Kconfig
drivers/net/ethernet/cadence/at91_ether.c
drivers/net/ethernet/cadence/at91_ether.h [deleted file]
drivers/net/ethernet/cadence/macb.c
drivers/net/ethernet/cadence/macb.h
drivers/net/ethernet/calxeda/xgmac.c
drivers/net/ethernet/chelsio/Kconfig
drivers/net/ethernet/chelsio/cxgb/cxgb2.c
drivers/net/ethernet/chelsio/cxgb/sge.c
drivers/net/ethernet/chelsio/cxgb/subr.c
drivers/net/ethernet/chelsio/cxgb/tp.c
drivers/net/ethernet/chelsio/cxgb3/common.h
drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c
drivers/net/ethernet/chelsio/cxgb3/t3_hw.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h
drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
drivers/net/ethernet/cisco/Kconfig
drivers/net/ethernet/cisco/enic/Kconfig
drivers/net/ethernet/cisco/enic/enic_main.c
drivers/net/ethernet/davicom/dm9000.c
drivers/net/ethernet/dec/ewrk3.c
drivers/net/ethernet/dec/tulip/de2104x.c
drivers/net/ethernet/dec/tulip/de4x5.c
drivers/net/ethernet/dec/tulip/dmfe.c
drivers/net/ethernet/dec/tulip/eeprom.c
drivers/net/ethernet/dec/tulip/media.c
drivers/net/ethernet/dec/tulip/tulip_core.c
drivers/net/ethernet/dec/tulip/uli526x.c
drivers/net/ethernet/dec/tulip/winbond-840.c
drivers/net/ethernet/dec/tulip/xircom_cb.c
drivers/net/ethernet/dlink/dl2k.c
drivers/net/ethernet/dlink/sundance.c
drivers/net/ethernet/dnet.c
drivers/net/ethernet/emulex/Kconfig
drivers/net/ethernet/emulex/benet/Kconfig
drivers/net/ethernet/emulex/benet/be.h
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/emulex/benet/be_cmds.h
drivers/net/ethernet/emulex/benet/be_ethtool.c
drivers/net/ethernet/emulex/benet/be_hw.h
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/emulex/benet/be_roce.c
drivers/net/ethernet/ethoc.c
drivers/net/ethernet/fealnx.c
drivers/net/ethernet/freescale/Kconfig
drivers/net/ethernet/freescale/Makefile
drivers/net/ethernet/freescale/fec.c
drivers/net/ethernet/freescale/fec.h
drivers/net/ethernet/freescale/fec_mpc52xx.c
drivers/net/ethernet/freescale/fec_ptp.c [new file with mode: 0644]
drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c
drivers/net/ethernet/freescale/fs_enet/mii-fec.c
drivers/net/ethernet/freescale/gianfar.c
drivers/net/ethernet/freescale/xgmac_mdio.c
drivers/net/ethernet/hp/hp100.c
drivers/net/ethernet/i825xx/ether1.c
drivers/net/ethernet/i825xx/lasi_82596.c
drivers/net/ethernet/i825xx/lib82596.c
drivers/net/ethernet/i825xx/sni_82596.c
drivers/net/ethernet/ibm/Kconfig
drivers/net/ethernet/ibm/ehea/ehea_main.c
drivers/net/ethernet/ibm/emac/core.c
drivers/net/ethernet/ibm/emac/mal.c
drivers/net/ethernet/ibm/emac/rgmii.c
drivers/net/ethernet/ibm/emac/tah.c
drivers/net/ethernet/ibm/emac/zmii.c
drivers/net/ethernet/ibm/ibmveth.c
drivers/net/ethernet/icplus/ipg.c
drivers/net/ethernet/intel/Kconfig
drivers/net/ethernet/intel/e100.c
drivers/net/ethernet/intel/e1000/e1000_ethtool.c
drivers/net/ethernet/intel/e1000/e1000_hw.c
drivers/net/ethernet/intel/e1000/e1000_main.c
drivers/net/ethernet/intel/e1000/e1000_param.c
drivers/net/ethernet/intel/e1000e/80003es2lan.c
drivers/net/ethernet/intel/e1000e/82571.c
drivers/net/ethernet/intel/e1000e/defines.h
drivers/net/ethernet/intel/e1000e/e1000.h
drivers/net/ethernet/intel/e1000e/ethtool.c
drivers/net/ethernet/intel/e1000e/hw.h
drivers/net/ethernet/intel/e1000e/ich8lan.c
drivers/net/ethernet/intel/e1000e/mac.c
drivers/net/ethernet/intel/e1000e/manage.c
drivers/net/ethernet/intel/e1000e/netdev.c
drivers/net/ethernet/intel/e1000e/nvm.c
drivers/net/ethernet/intel/e1000e/param.c
drivers/net/ethernet/intel/e1000e/phy.c
drivers/net/ethernet/intel/igb/Makefile
drivers/net/ethernet/intel/igb/e1000_82575.c
drivers/net/ethernet/intel/igb/e1000_82575.h
drivers/net/ethernet/intel/igb/e1000_defines.h
drivers/net/ethernet/intel/igb/e1000_i210.c
drivers/net/ethernet/intel/igb/e1000_i210.h
drivers/net/ethernet/intel/igb/e1000_mac.c
drivers/net/ethernet/intel/igb/e1000_mac.h
drivers/net/ethernet/intel/igb/e1000_nvm.c
drivers/net/ethernet/intel/igb/e1000_nvm.h
drivers/net/ethernet/intel/igb/e1000_phy.c
drivers/net/ethernet/intel/igb/e1000_phy.h
drivers/net/ethernet/intel/igb/igb.h
drivers/net/ethernet/intel/igb/igb_ethtool.c
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/intel/igb/igb_ptp.c
drivers/net/ethernet/intel/igbvf/defines.h
drivers/net/ethernet/intel/igbvf/igbvf.h
drivers/net/ethernet/intel/igbvf/netdev.c
drivers/net/ethernet/intel/ixgb/ixgb_main.c
drivers/net/ethernet/intel/ixgb/ixgb_param.c
drivers/net/ethernet/intel/ixgbe/Makefile
drivers/net/ethernet/intel/ixgbe/ixgbe.h
drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c
drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h
drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
drivers/net/ethernet/intel/ixgbevf/defines.h
drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
drivers/net/ethernet/intel/ixgbevf/mbx.h
drivers/net/ethernet/intel/ixgbevf/vf.c
drivers/net/ethernet/intel/ixgbevf/vf.h
drivers/net/ethernet/jme.c
drivers/net/ethernet/lantiq_etop.c
drivers/net/ethernet/marvell/pxa168_eth.c
drivers/net/ethernet/marvell/skge.c
drivers/net/ethernet/marvell/sky2.c
drivers/net/ethernet/mellanox/Kconfig
drivers/net/ethernet/mellanox/mlx4/Kconfig
drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
drivers/net/ethernet/mellanox/mlx4/en_main.c
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
drivers/net/ethernet/mellanox/mlx4/en_rx.c
drivers/net/ethernet/mellanox/mlx4/en_tx.c
drivers/net/ethernet/mellanox/mlx4/eq.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
drivers/net/ethernet/micrel/ks8695net.c
drivers/net/ethernet/micrel/ks8842.c
drivers/net/ethernet/micrel/ks8851.c
drivers/net/ethernet/micrel/ks8851_mll.c
drivers/net/ethernet/micrel/ksz884x.c
drivers/net/ethernet/microchip/enc28j60.c
drivers/net/ethernet/myricom/Kconfig
drivers/net/ethernet/myricom/myri10ge/myri10ge.c
drivers/net/ethernet/myricom/myri10ge/myri10ge_mcp_gen_header.h
drivers/net/ethernet/natsemi/ibmlana.c
drivers/net/ethernet/natsemi/jazzsonic.c
drivers/net/ethernet/natsemi/macsonic.c
drivers/net/ethernet/natsemi/natsemi.c
drivers/net/ethernet/natsemi/ns83820.c
drivers/net/ethernet/natsemi/xtsonic.c
drivers/net/ethernet/neterion/Kconfig
drivers/net/ethernet/neterion/s2io.c
drivers/net/ethernet/neterion/s2io.h
drivers/net/ethernet/neterion/vxge/vxge-config.c
drivers/net/ethernet/neterion/vxge/vxge-config.h
drivers/net/ethernet/neterion/vxge/vxge-main.c
drivers/net/ethernet/nuvoton/w90p910_ether.c
drivers/net/ethernet/nvidia/forcedeth.c
drivers/net/ethernet/nxp/lpc_eth.c
drivers/net/ethernet/octeon/octeon_mgmt.c
drivers/net/ethernet/oki-semi/pch_gbe/Kconfig
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
drivers/net/ethernet/packetengines/hamachi.c
drivers/net/ethernet/packetengines/yellowfin.c
drivers/net/ethernet/pasemi/pasemi_mac.c
drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c
drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
drivers/net/ethernet/qlogic/qla3xxx.c
drivers/net/ethernet/qlogic/qlcnic/Makefile
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c [new file with mode: 0644]
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c [new file with mode: 0644]
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c [new file with mode: 0644]
drivers/net/ethernet/qlogic/qlge/qlge_dbg.c
drivers/net/ethernet/qlogic/qlge/qlge_main.c
drivers/net/ethernet/rdc/r6040.c
drivers/net/ethernet/realtek/8139cp.c
drivers/net/ethernet/realtek/8139too.c
drivers/net/ethernet/realtek/atp.c
drivers/net/ethernet/realtek/atp.h
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/s6gmac.c
drivers/net/ethernet/seeq/ether3.c
drivers/net/ethernet/seeq/sgiseeq.c
drivers/net/ethernet/sfc/Kconfig
drivers/net/ethernet/sfc/Makefile
drivers/net/ethernet/sfc/efx.c
drivers/net/ethernet/sfc/efx.h
drivers/net/ethernet/sfc/ethtool.c
drivers/net/ethernet/sfc/falcon.c
drivers/net/ethernet/sfc/io.h
drivers/net/ethernet/sfc/mcdi.c
drivers/net/ethernet/sfc/net_driver.h
drivers/net/ethernet/sfc/nic.c
drivers/net/ethernet/sfc/nic.h
drivers/net/ethernet/sfc/rx.c
drivers/net/ethernet/sfc/selftest.c
drivers/net/ethernet/sfc/siena.c
drivers/net/ethernet/sfc/siena_sriov.c
drivers/net/ethernet/sgi/ioc3-eth.c
drivers/net/ethernet/sgi/meth.c
drivers/net/ethernet/silan/sc92031.c
drivers/net/ethernet/sis/sis190.c
drivers/net/ethernet/sis/sis900.c
drivers/net/ethernet/smsc/epic100.c
drivers/net/ethernet/smsc/smc911x.c
drivers/net/ethernet/smsc/smc911x.h
drivers/net/ethernet/smsc/smc91x.c
drivers/net/ethernet/smsc/smc91x.h
drivers/net/ethernet/smsc/smsc911x.c
drivers/net/ethernet/smsc/smsc9420.c
drivers/net/ethernet/stmicro/stmmac/Kconfig
drivers/net/ethernet/stmicro/stmmac/Makefile
drivers/net/ethernet/stmicro/stmmac/common.h
drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
drivers/net/ethernet/stmicro/stmmac/stmmac.h
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c [deleted file]
drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h [deleted file]
drivers/net/ethernet/sun/cassini.c
drivers/net/ethernet/sun/niu.c
drivers/net/ethernet/sun/sunbmac.c
drivers/net/ethernet/sun/sungem.c
drivers/net/ethernet/sun/sunhme.c
drivers/net/ethernet/sun/sunqe.c
drivers/net/ethernet/sun/sunvnet.c
drivers/net/ethernet/tehuti/tehuti.c
drivers/net/ethernet/ti/Kconfig
drivers/net/ethernet/ti/Makefile
drivers/net/ethernet/ti/cpmac.c
drivers/net/ethernet/ti/cpsw.c
drivers/net/ethernet/ti/cpsw_ale.c
drivers/net/ethernet/ti/cpsw_ale.h
drivers/net/ethernet/ti/cpts.c [new file with mode: 0644]
drivers/net/ethernet/ti/cpts.h [new file with mode: 0644]
drivers/net/ethernet/ti/davinci_emac.c
drivers/net/ethernet/ti/davinci_mdio.c
drivers/net/ethernet/ti/tlan.c
drivers/net/ethernet/toshiba/ps3_gelic_net.c
drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
drivers/net/ethernet/toshiba/spider_net.c
drivers/net/ethernet/toshiba/tc35815.c
drivers/net/ethernet/via/via-rhine.c
drivers/net/ethernet/via/via-velocity.c
drivers/net/ethernet/wiznet/w5100.c
drivers/net/ethernet/wiznet/w5300.c
drivers/net/ethernet/xilinx/ll_temac_main.c
drivers/net/ethernet/xilinx/xilinx_axienet_main.c
drivers/net/ethernet/xilinx/xilinx_emaclite.c
drivers/net/ethernet/xscale/ixp4xx_eth.c
drivers/net/fddi/defxx.c
drivers/net/fddi/skfp/skfddi.c
drivers/net/hippi/rrunner.c
drivers/net/hyperv/rndis_filter.c
drivers/net/ieee802154/at86rf230.c
drivers/net/ieee802154/fakehard.c
drivers/net/ieee802154/fakelb.c
drivers/net/ieee802154/mrf24j40.c
drivers/net/irda/au1k_ir.c
drivers/net/irda/bfin_sir.c
drivers/net/irda/ep7211-sir.c
drivers/net/irda/sh_irda.c
drivers/net/irda/sh_sir.c
drivers/net/irda/smsc-ircc2.c
drivers/net/irda/via-ircc.c
drivers/net/irda/vlsi_ir.c
drivers/net/netconsole.c
drivers/net/phy/davicom.c
drivers/net/phy/dp83640.c
drivers/net/phy/mdio-gpio.c
drivers/net/phy/mdio-mux-gpio.c
drivers/net/phy/mdio-mux-mmioreg.c
drivers/net/phy/mdio-octeon.c
drivers/net/phy/mdio_bus.c
drivers/net/phy/micrel.c
drivers/net/phy/smsc.c
drivers/net/phy/spi_ks8995.c
drivers/net/ppp/ppp_generic.c
drivers/net/sungem_phy.c
drivers/net/tun.c
drivers/net/usb/Kconfig
drivers/net/usb/Makefile
drivers/net/usb/asix_common.c
drivers/net/usb/asix_devices.c
drivers/net/usb/cdc_mbim.c [new file with mode: 0644]
drivers/net/usb/cdc_ncm.c
drivers/net/usb/dm9601.c
drivers/net/usb/int51x1.c
drivers/net/usb/mcs7830.c
drivers/net/usb/net1080.c
drivers/net/usb/plusb.c
drivers/net/usb/sierra_net.c
drivers/net/usb/smsc75xx.c
drivers/net/usb/smsc95xx.c
drivers/net/usb/smsc95xx.h
drivers/net/usb/usbnet.c
drivers/net/veth.c
drivers/net/virtio_net.c
drivers/net/vmxnet3/vmxnet3_drv.c
drivers/net/vxlan.c
drivers/net/wan/Makefile
drivers/net/wan/dscc4.c
drivers/net/wan/farsync.c
drivers/net/wan/hd64570.c
drivers/net/wan/hd64572.c
drivers/net/wan/ixp4xx_hss.c
drivers/net/wan/lmc/lmc_main.c
drivers/net/wan/pc300too.c
drivers/net/wan/pci200syn.c
drivers/net/wan/wanxl.c
drivers/net/wan/wanxlfw.S
drivers/net/wimax/i2400m/debugfs.c
drivers/net/wireless/adm8211.c
drivers/net/wireless/airo.c
drivers/net/wireless/at76c50x-usb.c
drivers/net/wireless/ath/Kconfig
drivers/net/wireless/ath/Makefile
drivers/net/wireless/ath/ar5523/Kconfig [new file with mode: 0644]
drivers/net/wireless/ath/ar5523/Makefile [new file with mode: 0644]
drivers/net/wireless/ath/ar5523/ar5523.c [new file with mode: 0644]
drivers/net/wireless/ath/ar5523/ar5523.h [new file with mode: 0644]
drivers/net/wireless/ath/ar5523/ar5523_hw.h [new file with mode: 0644]
drivers/net/wireless/ath/ath5k/Kconfig
drivers/net/wireless/ath/ath5k/ahb.c
drivers/net/wireless/ath/ath5k/base.c
drivers/net/wireless/ath/ath5k/led.c
drivers/net/wireless/ath/ath5k/mac80211-ops.c
drivers/net/wireless/ath/ath5k/pci.c
drivers/net/wireless/ath/ath5k/reset.c
drivers/net/wireless/ath/ath6kl/Kconfig
drivers/net/wireless/ath/ath6kl/Makefile
drivers/net/wireless/ath/ath6kl/cfg80211.c
drivers/net/wireless/ath/ath6kl/cfg80211.h
drivers/net/wireless/ath/ath6kl/core.c
drivers/net/wireless/ath/ath6kl/core.h
drivers/net/wireless/ath/ath6kl/debug.h
drivers/net/wireless/ath/ath6kl/hif.c
drivers/net/wireless/ath/ath6kl/htc_mbox.c
drivers/net/wireless/ath/ath6kl/htc_pipe.c
drivers/net/wireless/ath/ath6kl/init.c
drivers/net/wireless/ath/ath6kl/main.c
drivers/net/wireless/ath/ath6kl/recovery.c [new file with mode: 0644]
drivers/net/wireless/ath/ath6kl/sdio.c
drivers/net/wireless/ath/ath6kl/txrx.c
drivers/net/wireless/ath/ath6kl/usb.c
drivers/net/wireless/ath/ath6kl/wmi.c
drivers/net/wireless/ath/ath6kl/wmi.h
drivers/net/wireless/ath/ath9k/Kconfig
drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
drivers/net/wireless/ath/ath9k/ar9003_calib.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
drivers/net/wireless/ath/ath9k/ar9003_hw.c
drivers/net/wireless/ath/ath9k/ar9003_mci.c
drivers/net/wireless/ath/ath9k/ar9003_mci.h
drivers/net/wireless/ath/ath9k/ar9003_paprd.c
drivers/net/wireless/ath/ath9k/ar9003_phy.c
drivers/net/wireless/ath/ath9k/ar9003_phy.h
drivers/net/wireless/ath/ath9k/ar9340_initvals.h
drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h
drivers/net/wireless/ath/ath9k/ar9485_initvals.h
drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/beacon.c
drivers/net/wireless/ath/ath9k/btcoex.c
drivers/net/wireless/ath/ath9k/btcoex.h
drivers/net/wireless/ath/ath9k/calib.c
drivers/net/wireless/ath/ath9k/calib.h
drivers/net/wireless/ath/ath9k/common.h
drivers/net/wireless/ath/ath9k/debug.c
drivers/net/wireless/ath/ath9k/debug.h
drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c
drivers/net/wireless/ath/ath9k/dfs_pattern_detector.h
drivers/net/wireless/ath/ath9k/eeprom.c
drivers/net/wireless/ath/ath9k/eeprom.h
drivers/net/wireless/ath/ath9k/eeprom_4k.c
drivers/net/wireless/ath/ath9k/eeprom_9287.c
drivers/net/wireless/ath/ath9k/eeprom_def.c
drivers/net/wireless/ath/ath9k/gpio.c
drivers/net/wireless/ath/ath9k/htc.h
drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
drivers/net/wireless/ath/ath9k/htc_drv_debug.c
drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
drivers/net/wireless/ath/ath9k/htc_drv_init.c
drivers/net/wireless/ath/ath9k/htc_drv_main.c
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/hw.h
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/ath/ath9k/link.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/mci.c
drivers/net/wireless/ath/ath9k/mci.h
drivers/net/wireless/ath/ath9k/pci.c
drivers/net/wireless/ath/ath9k/rc.c
drivers/net/wireless/ath/ath9k/rc.h
drivers/net/wireless/ath/ath9k/recv.c
drivers/net/wireless/ath/ath9k/reg.h
drivers/net/wireless/ath/ath9k/wow.c
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/ath/carl9170/Kconfig
drivers/net/wireless/ath/carl9170/fw.c
drivers/net/wireless/ath/carl9170/mac.c
drivers/net/wireless/ath/carl9170/rx.c
drivers/net/wireless/ath/carl9170/tx.c
drivers/net/wireless/ath/carl9170/usb.c
drivers/net/wireless/ath/hw.c
drivers/net/wireless/atmel.c
drivers/net/wireless/atmel_pci.c
drivers/net/wireless/b43/dma.c
drivers/net/wireless/b43/main.c
drivers/net/wireless/b43/pcmcia.c
drivers/net/wireless/b43/pio.c
drivers/net/wireless/b43/sdio.c
drivers/net/wireless/b43/xmit.c
drivers/net/wireless/b43legacy/b43legacy.h
drivers/net/wireless/b43legacy/main.c
drivers/net/wireless/b43legacy/xmit.c
drivers/net/wireless/brcm80211/Kconfig
drivers/net/wireless/brcm80211/brcmfmac/Makefile
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
drivers/net/wireless/brcm80211/brcmfmac/dhd.h
drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c
drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
drivers/net/wireless/brcm80211/brcmfmac/fweh.c [new file with mode: 0644]
drivers/net/wireless/brcm80211/brcmfmac/fweh.h [new file with mode: 0644]
drivers/net/wireless/brcm80211/brcmfmac/fwil.c [new file with mode: 0644]
drivers/net/wireless/brcm80211/brcmfmac/fwil.h [new file with mode: 0644]
drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c
drivers/net/wireless/brcm80211/brcmfmac/usb.c
drivers/net/wireless/brcm80211/brcmfmac/usb.h
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
drivers/net/wireless/brcm80211/brcmsmac/Makefile
drivers/net/wireless/brcm80211/brcmsmac/aiutils.c
drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
drivers/net/wireless/brcm80211/brcmsmac/ampdu.h
drivers/net/wireless/brcm80211/brcmsmac/antsel.c
drivers/net/wireless/brcm80211/brcmsmac/brcms_trace_events.h
drivers/net/wireless/brcm80211/brcmsmac/channel.c
drivers/net/wireless/brcm80211/brcmsmac/debug.c [new file with mode: 0644]
drivers/net/wireless/brcm80211/brcmsmac/debug.h [new file with mode: 0644]
drivers/net/wireless/brcm80211/brcmsmac/dma.c
drivers/net/wireless/brcm80211/brcmsmac/dma.h
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
drivers/net/wireless/brcm80211/brcmsmac/main.c
drivers/net/wireless/brcm80211/brcmsmac/main.h
drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c
drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c
drivers/net/wireless/brcm80211/brcmsmac/pub.h
drivers/net/wireless/brcm80211/brcmsmac/stf.c
drivers/net/wireless/brcm80211/brcmsmac/types.h
drivers/net/wireless/brcm80211/include/defs.h
drivers/net/wireless/hostap/hostap_80211_rx.c
drivers/net/wireless/ipw2x00/ipw2100.c
drivers/net/wireless/ipw2x00/ipw2100.h
drivers/net/wireless/ipw2x00/ipw2200.c
drivers/net/wireless/ipw2x00/libipw.h
drivers/net/wireless/ipw2x00/libipw_geo.c
drivers/net/wireless/ipw2x00/libipw_rx.c
drivers/net/wireless/iwlegacy/3945-mac.c
drivers/net/wireless/iwlegacy/3945.c
drivers/net/wireless/iwlegacy/4965-mac.c
drivers/net/wireless/iwlegacy/4965.h
drivers/net/wireless/iwlegacy/common.c
drivers/net/wireless/iwlegacy/common.h
drivers/net/wireless/iwlwifi/Kconfig
drivers/net/wireless/iwlwifi/dvm/agn.h
drivers/net/wireless/iwlwifi/dvm/calib.c
drivers/net/wireless/iwlwifi/dvm/commands.h
drivers/net/wireless/iwlwifi/dvm/debugfs.c
drivers/net/wireless/iwlwifi/dvm/dev.h
drivers/net/wireless/iwlwifi/dvm/devices.c
drivers/net/wireless/iwlwifi/dvm/lib.c
drivers/net/wireless/iwlwifi/dvm/mac80211.c
drivers/net/wireless/iwlwifi/dvm/main.c
drivers/net/wireless/iwlwifi/dvm/rs.c
drivers/net/wireless/iwlwifi/dvm/rx.c
drivers/net/wireless/iwlwifi/dvm/rxon.c
drivers/net/wireless/iwlwifi/dvm/scan.c
drivers/net/wireless/iwlwifi/dvm/sta.c
drivers/net/wireless/iwlwifi/dvm/tx.c
drivers/net/wireless/iwlwifi/dvm/ucode.c
drivers/net/wireless/iwlwifi/iwl-config.h
drivers/net/wireless/iwlwifi/iwl-devtrace.h
drivers/net/wireless/iwlwifi/iwl-drv.c
drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c
drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h
drivers/net/wireless/iwlwifi/iwl-fh.h
drivers/net/wireless/iwlwifi/iwl-io.c
drivers/net/wireless/iwlwifi/iwl-io.h
drivers/net/wireless/iwlwifi/iwl-prph.h
drivers/net/wireless/iwlwifi/iwl-trans.h
drivers/net/wireless/iwlwifi/pcie/1000.c
drivers/net/wireless/iwlwifi/pcie/2000.c
drivers/net/wireless/iwlwifi/pcie/5000.c
drivers/net/wireless/iwlwifi/pcie/6000.c
drivers/net/wireless/iwlwifi/pcie/drv.c
drivers/net/wireless/iwlwifi/pcie/internal.h
drivers/net/wireless/iwlwifi/pcie/rx.c
drivers/net/wireless/iwlwifi/pcie/trans.c
drivers/net/wireless/iwlwifi/pcie/tx.c
drivers/net/wireless/libertas/cfg.c
drivers/net/wireless/libertas/if_sdio.c
drivers/net/wireless/libertas/if_spi.c
drivers/net/wireless/libertas/mesh.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/mwifiex/11n_aggr.c
drivers/net/wireless/mwifiex/11n_rxreorder.c
drivers/net/wireless/mwifiex/Kconfig
drivers/net/wireless/mwifiex/cfg80211.c
drivers/net/wireless/mwifiex/cmdevt.c
drivers/net/wireless/mwifiex/debugfs.c
drivers/net/wireless/mwifiex/fw.h
drivers/net/wireless/mwifiex/init.c
drivers/net/wireless/mwifiex/join.c
drivers/net/wireless/mwifiex/main.c
drivers/net/wireless/mwifiex/main.h
drivers/net/wireless/mwifiex/scan.c
drivers/net/wireless/mwifiex/sdio.c
drivers/net/wireless/mwifiex/sdio.h
drivers/net/wireless/mwifiex/sta_cmdresp.c
drivers/net/wireless/mwifiex/sta_event.c
drivers/net/wireless/mwifiex/sta_ioctl.c
drivers/net/wireless/mwifiex/sta_rx.c
drivers/net/wireless/mwifiex/txrx.c
drivers/net/wireless/mwifiex/uap_cmd.c
drivers/net/wireless/mwifiex/uap_event.c
drivers/net/wireless/mwifiex/uap_txrx.c
drivers/net/wireless/mwifiex/usb.c
drivers/net/wireless/mwifiex/util.c
drivers/net/wireless/mwifiex/wmm.c
drivers/net/wireless/mwifiex/wmm.h
drivers/net/wireless/mwl8k.c
drivers/net/wireless/orinoco/cfg.c
drivers/net/wireless/orinoco/main.h
drivers/net/wireless/orinoco/orinoco_nortel.c
drivers/net/wireless/orinoco/orinoco_pci.c
drivers/net/wireless/orinoco/orinoco_plx.c
drivers/net/wireless/orinoco/orinoco_tmd.c
drivers/net/wireless/orinoco/orinoco_usb.c
drivers/net/wireless/p54/eeprom.c
drivers/net/wireless/p54/p54pci.c
drivers/net/wireless/p54/p54spi.c
drivers/net/wireless/p54/p54usb.c
drivers/net/wireless/p54/txrx.c
drivers/net/wireless/rndis_wlan.c
drivers/net/wireless/rt2x00/rt2400pci.c
drivers/net/wireless/rt2x00/rt2500pci.c
drivers/net/wireless/rt2x00/rt2800.h
drivers/net/wireless/rt2x00/rt2800lib.c
drivers/net/wireless/rt2x00/rt2800pci.c
drivers/net/wireless/rt2x00/rt2800usb.c
drivers/net/wireless/rt2x00/rt2x00dev.c
drivers/net/wireless/rt2x00/rt2x00mac.c
drivers/net/wireless/rt2x00/rt61pci.c
drivers/net/wireless/rtl818x/rtl8180/dev.c
drivers/net/wireless/rtl818x/rtl8187/dev.c
drivers/net/wireless/rtlwifi/Kconfig
drivers/net/wireless/rtlwifi/Makefile
drivers/net/wireless/rtlwifi/base.c
drivers/net/wireless/rtlwifi/base.h
drivers/net/wireless/rtlwifi/cam.c
drivers/net/wireless/rtlwifi/core.c
drivers/net/wireless/rtlwifi/debug.h
drivers/net/wireless/rtlwifi/pci.c
drivers/net/wireless/rtlwifi/pci.h
drivers/net/wireless/rtlwifi/rc.c
drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
drivers/net/wireless/rtlwifi/rtl8192ce/def.h
drivers/net/wireless/rtlwifi/rtl8192ce/dm.c
drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
drivers/net/wireless/rtlwifi/rtl8192ce/phy.c
drivers/net/wireless/rtlwifi/rtl8192ce/rf.c
drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
drivers/net/wireless/rtlwifi/rtl8192cu/dm.c
drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
drivers/net/wireless/rtlwifi/rtl8192de/dm.c
drivers/net/wireless/rtlwifi/rtl8192de/phy.c
drivers/net/wireless/rtlwifi/rtl8192de/rf.c
drivers/net/wireless/rtlwifi/rtl8192de/sw.c
drivers/net/wireless/rtlwifi/rtl8192de/trx.c
drivers/net/wireless/rtlwifi/rtl8192se/def.h
drivers/net/wireless/rtlwifi/rtl8192se/dm.c
drivers/net/wireless/rtlwifi/rtl8192se/hw.c
drivers/net/wireless/rtlwifi/rtl8192se/hw.h
drivers/net/wireless/rtlwifi/rtl8192se/phy.c
drivers/net/wireless/rtlwifi/rtl8192se/rf.c
drivers/net/wireless/rtlwifi/rtl8192se/sw.c
drivers/net/wireless/rtlwifi/rtl8192se/trx.c
drivers/net/wireless/rtlwifi/rtl8723ae/Makefile [new file with mode: 0644]
drivers/net/wireless/rtlwifi/rtl8723ae/btc.h [new file with mode: 0644]
drivers/net/wireless/rtlwifi/rtl8723ae/def.h [new file with mode: 0644]
drivers/net/wireless/rtlwifi/rtl8723ae/dm.c [new file with mode: 0644]
drivers/net/wireless/rtlwifi/rtl8723ae/dm.h [new file with mode: 0644]
drivers/net/wireless/rtlwifi/rtl8723ae/fw.c [new file with mode: 0644]
drivers/net/wireless/rtlwifi/rtl8723ae/fw.h [new file with mode: 0644]
drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.c [new file with mode: 0644]
drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.h [new file with mode: 0644]
drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.c [new file with mode: 0644]
drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.h [new file with mode: 0644]
drivers/net/wireless/rtlwifi/rtl8723ae/hw.c [new file with mode: 0644]
drivers/net/wireless/rtlwifi/rtl8723ae/hw.h [new file with mode: 0644]
drivers/net/wireless/rtlwifi/rtl8723ae/led.c [new file with mode: 0644]
drivers/net/wireless/rtlwifi/rtl8723ae/led.h [new file with mode: 0644]
drivers/net/wireless/rtlwifi/rtl8723ae/phy.c [new file with mode: 0644]
drivers/net/wireless/rtlwifi/rtl8723ae/phy.h [new file with mode: 0644]
drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.c [new file with mode: 0644]
drivers/net/wireless/rtlwifi/rtl8723ae/pwrseq.h [new file with mode: 0644]
drivers/net/wireless/rtlwifi/rtl8723ae/pwrseqcmd.c [new file with mode: 0644]
drivers/net/wireless/rtlwifi/rtl8723ae/pwrseqcmd.h [new file with mode: 0644]
drivers/net/wireless/rtlwifi/rtl8723ae/reg.h [new file with mode: 0644]
drivers/net/wireless/rtlwifi/rtl8723ae/rf.c [new file with mode: 0644]
drivers/net/wireless/rtlwifi/rtl8723ae/rf.h [new file with mode: 0644]
drivers/net/wireless/rtlwifi/rtl8723ae/sw.c [new file with mode: 0644]
drivers/net/wireless/rtlwifi/rtl8723ae/sw.h [new file with mode: 0644]
drivers/net/wireless/rtlwifi/rtl8723ae/table.c [new file with mode: 0644]
drivers/net/wireless/rtlwifi/rtl8723ae/table.h [new file with mode: 0644]
drivers/net/wireless/rtlwifi/rtl8723ae/trx.c [new file with mode: 0644]
drivers/net/wireless/rtlwifi/rtl8723ae/trx.h [new file with mode: 0644]
drivers/net/wireless/rtlwifi/stats.c [new file with mode: 0644]
drivers/net/wireless/rtlwifi/stats.h [new file with mode: 0644]
drivers/net/wireless/rtlwifi/usb.c
drivers/net/wireless/rtlwifi/usb.h
drivers/net/wireless/rtlwifi/wifi.h
drivers/net/wireless/ti/wl1251/main.c
drivers/net/wireless/ti/wl1251/rx.c
drivers/net/wireless/ti/wl1251/sdio.c
drivers/net/wireless/ti/wl1251/spi.c
drivers/net/wireless/ti/wl12xx/main.c
drivers/net/wireless/ti/wl18xx/main.c
drivers/net/wireless/ti/wlcore/cmd.c
drivers/net/wireless/ti/wlcore/main.c
drivers/net/wireless/ti/wlcore/sdio.c
drivers/net/wireless/ti/wlcore/spi.c
drivers/net/wireless/ti/wlcore/wlcore.h
drivers/net/wireless/zd1211rw/zd_chip.c
drivers/net/xen-netfront.c
drivers/nfc/Makefile
drivers/nfc/pn533.c
drivers/nfc/pn544/Makefile [new file with mode: 0644]
drivers/nfc/pn544/i2c.c [new file with mode: 0644]
drivers/nfc/pn544/pn544.c [moved from drivers/nfc/pn544_hci.c with 58% similarity]
drivers/nfc/pn544/pn544.h [new file with mode: 0644]
drivers/pci/bus.c
drivers/pci/ioapic.c
drivers/pci/iov.c
drivers/pci/irq.c
drivers/pci/pci-driver.c
drivers/pci/pci-stub.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/pcie/aer/aerdrv.h
drivers/pci/pcie/aer/aerdrv_core.c
drivers/pci/pcie/aspm.c
drivers/pci/pcie/portdrv_core.c
drivers/pci/probe.c
drivers/pci/quirks.c
drivers/pci/remove.c
drivers/pci/rom.c
drivers/pci/setup-bus.c
drivers/pci/xen-pcifront.c
drivers/pinctrl/mvebu/pinctrl-dove.c
drivers/pinctrl/mvebu/pinctrl-kirkwood.c
drivers/pinctrl/pinctrl-nomadik.c
drivers/power/Kconfig
drivers/power/Makefile
drivers/power/avs/smartreflex.c
drivers/power/reset/Kconfig [new file with mode: 0644]
drivers/power/reset/Makefile [new file with mode: 0644]
drivers/power/reset/gpio-poweroff.c [new file with mode: 0644]
drivers/pps/Kconfig
drivers/ptp/Kconfig
drivers/ptp/ptp_chardev.c
drivers/regulator/88pm8607.c
drivers/regulator/Kconfig
drivers/regulator/Makefile
drivers/regulator/aat2870-regulator.c
drivers/regulator/ab3100.c
drivers/regulator/ab8500.c
drivers/regulator/ad5398.c
drivers/regulator/anatop-regulator.c
drivers/regulator/arizona-ldo1.c
drivers/regulator/arizona-micsupp.c
drivers/regulator/as3711-regulator.c [new file with mode: 0644]
drivers/regulator/core.c
drivers/regulator/da903x.c
drivers/regulator/da9052-regulator.c
drivers/regulator/da9055-regulator.c [new file with mode: 0644]
drivers/regulator/db8500-prcmu.c
drivers/regulator/dbx500-prcmu.c
drivers/regulator/dummy.c
drivers/regulator/fan53555.c
drivers/regulator/fixed.c
drivers/regulator/gpio-regulator.c
drivers/regulator/isl6271a-regulator.c
drivers/regulator/lp3971.c
drivers/regulator/lp3972.c
drivers/regulator/lp872x.c
drivers/regulator/lp8788-buck.c
drivers/regulator/lp8788-ldo.c
drivers/regulator/max1586.c
drivers/regulator/max77686.c
drivers/regulator/max8649.c
drivers/regulator/max8660.c
drivers/regulator/max8907-regulator.c
drivers/regulator/max8925-regulator.c
drivers/regulator/max8952.c
drivers/regulator/max8973-regulator.c [new file with mode: 0644]
drivers/regulator/max8997.c
drivers/regulator/max8998.c
drivers/regulator/mc13783-regulator.c
drivers/regulator/mc13892-regulator.c
drivers/regulator/mc13xxx-regulator-core.c
drivers/regulator/palmas-regulator.c
drivers/regulator/pcap-regulator.c
drivers/regulator/pcf50633-regulator.c
drivers/regulator/rc5t583-regulator.c
drivers/regulator/s2mps11.c
drivers/regulator/s5m8767.c
drivers/regulator/tps51632-regulator.c [new file with mode: 0644]
drivers/regulator/tps6105x-regulator.c
drivers/regulator/tps62360-regulator.c
drivers/regulator/tps65023-regulator.c
drivers/regulator/tps6507x-regulator.c
drivers/regulator/tps65090-regulator.c
drivers/regulator/tps65217-regulator.c
drivers/regulator/tps6524x-regulator.c
drivers/regulator/tps6586x-regulator.c
drivers/regulator/tps65910-regulator.c
drivers/regulator/tps65912-regulator.c
drivers/regulator/tps80031-regulator.c [new file with mode: 0644]
drivers/regulator/twl-regulator.c
drivers/regulator/vexpress.c [new file with mode: 0644]
drivers/regulator/virtual.c
drivers/regulator/wm831x-dcdc.c
drivers/regulator/wm831x-isink.c
drivers/regulator/wm831x-ldo.c
drivers/regulator/wm8400-regulator.c
drivers/regulator/wm8994-regulator.c
drivers/remoteproc/remoteproc_elf_loader.c
drivers/rtc/rtc-isl1208.c
drivers/rtc/rtc-s3c.c
drivers/s390/block/dasd_devmap.c
drivers/s390/net/claw.c
drivers/s390/net/ctcm_main.c
drivers/s390/net/ctcm_mpc.c
drivers/s390/net/qeth_core.h
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_l2_main.c
drivers/s390/net/qeth_l3_main.c
drivers/scsi/bnx2fc/bnx2fc_hwi.c
drivers/scsi/libsas/sas_expander.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_nx.c
drivers/scsi/qla2xxx/qla_target.c
drivers/scsi/qla2xxx/tcm_qla2xxx.c
drivers/ssb/b43_pci_bridge.c
drivers/ssb/driver_chipcommon.c
drivers/ssb/driver_chipcommon_pmu.c
drivers/ssb/driver_extif.c
drivers/ssb/driver_mipscore.c
drivers/ssb/embedded.c
drivers/ssb/main.c
drivers/ssb/ssb_private.h
drivers/staging/comedi/drivers/usbdux.c
drivers/staging/tidspbridge/rmgr/node.c
drivers/target/iscsi/iscsi_target_configfs.c
drivers/target/iscsi/iscsi_target_erl0.c
drivers/target/iscsi/iscsi_target_parameters.c
drivers/target/iscsi/iscsi_target_util.c
drivers/thermal/Kconfig
drivers/tty/hvc/hvc_opal.c
drivers/tty/hvc/hvc_vio.c
drivers/tty/ipwireless/setup_protocol.h
drivers/tty/serial/8250/Kconfig
drivers/tty/serial/bfin_uart.c
drivers/tty/serial/icom.c
drivers/usb/core/driver.c
drivers/usb/gadget/at91_udc.c
drivers/usb/gadget/omap_udc.c
drivers/usb/host/ehci-orion.c
drivers/usb/musb/tusb6010_omap.c
drivers/usb/storage/realtek_cr.c
drivers/vhost/net.c
drivers/vhost/tcm_vhost.c
drivers/vhost/vhost.c
drivers/vhost/vhost.h
drivers/video/omap/lcdc.c
drivers/video/omap/omapfb_main.c
drivers/video/omap/sossi.c
drivers/watchdog/at91sam9_wdt.c
drivers/watchdog/booke_wdt.c
drivers/watchdog/omap_wdt.c
drivers/xen/xen-pciback/pci_stub.c
fs/btrfs/ctree.h
fs/btrfs/extent-tree.c
fs/btrfs/extent_map.c
fs/btrfs/ordered-data.h
fs/btrfs/volumes.c
fs/cifs/README
fs/ext4/ext4.h
fs/fhandle.c
fs/hugetlbfs/inode.c
fs/jbd/transaction.c
fs/jbd2/transaction.c
fs/logfs/inode.c
fs/ncpfs/mmap.c
fs/notify/fanotify/Kconfig
fs/notify/notification.c
fs/proc/proc_sysctl.c
include/acpi/acpi_drivers.h
include/linux/ath9k_platform.h
include/linux/atmdev.h
include/linux/atmel-ssc.h
include/linux/bcm47xx_wdt.h [new file with mode: 0644]
include/linux/bcma/bcma.h
include/linux/bcma/bcma_driver_chipcommon.h
include/linux/bcma/bcma_driver_mips.h
include/linux/bcma/bcma_regs.h
include/linux/clk/zynq.h [moved from arch/arm/mach-vt8500/include/mach/irqs.h with 78% similarity]
include/linux/dlm.h
include/linux/efi.h
include/linux/etherdevice.h
include/linux/filter.h
include/linux/hash.h
include/linux/hdlc/Kbuild
include/linux/hid-sensor-ids.h
include/linux/hid.h
include/linux/i2c/i2c-hid.h [new file with mode: 0644]
include/linux/ieee80211.h
include/linux/if_tunnel.h
include/linux/inetdevice.h
include/linux/input/mt.h
include/linux/ip.h
include/linux/ipmi_smi.h
include/linux/ipv6.h
include/linux/ktime.h
include/linux/lru_cache.h
include/linux/mfd/arizona/core.h
include/linux/mfd/arizona/pdata.h
include/linux/mfd/arizona/registers.h
include/linux/mfd/da9055/pdata.h
include/linux/mfd/max8997-private.h
include/linux/mfd/max8997.h
include/linux/mfd/tps65090.h
include/linux/mfd/tps6586x.h
include/linux/mfd/wm8994/core.h
include/linux/mfd/wm8994/pdata.h
include/linux/micrel_phy.h
include/linux/netdevice.h
include/linux/netfilter_ipv6/ip6_tables.h
include/linux/nfc/pn544.h [deleted file]
include/linux/omap-dma.h
include/linux/openvswitch.h
include/linux/pci.h
include/linux/platform_data/asoc-s3c.h
include/linux/platform_data/clocksource-nomadik-mtu.h [moved from arch/arm/plat-nomadik/include/plat/mtu.h with 71% similarity]
include/linux/platform_data/cpsw.h
include/linux/platform_data/crypto-ux500.h
include/linux/platform_data/davinci_asp.h
include/linux/platform_data/dma-ste-dma40.h [moved from arch/arm/plat-nomadik/include/plat/ste_dma40.h with 100% similarity]
include/linux/platform_data/macb.h
include/linux/platform_data/omap-twl4030.h
include/linux/platform_data/pn544.h [new file with mode: 0644]
include/linux/power/smartreflex.h
include/linux/regulator/consumer.h
include/linux/regulator/driver.h
include/linux/regulator/max8973-regulator.h [new file with mode: 0644]
include/linux/regulator/tps51632-regulator.h [new file with mode: 0644]
include/linux/regulator/tps65090-regulator.h [deleted file]
include/linux/rtnetlink.h
include/linux/skbuff.h
include/linux/smscphy.h
include/linux/ssb/ssb.h
include/linux/ssb/ssb_driver_chipcommon.h
include/linux/ssb/ssb_driver_extif.h
include/linux/ssb/ssb_driver_mips.h
include/linux/ssb/ssb_regs.h
include/linux/stmmac.h
include/linux/sysctl.h
include/linux/tcp.h
include/linux/timecompare.h [deleted file]
include/linux/udp.h
include/linux/usb/cdc_ncm.h [new file with mode: 0644]
include/linux/usb/usbnet.h
include/linux/vgaarb.h
include/linux/watchdog.h
include/net/addrconf.h
include/net/af_unix.h
include/net/bluetooth/a2mp.h
include/net/bluetooth/amp.h [new file with mode: 0644]
include/net/bluetooth/bluetooth.h
include/net/bluetooth/hci.h
include/net/bluetooth/hci_core.h
include/net/bluetooth/l2cap.h
include/net/cfg80211.h
include/net/cls_cgroup.h
include/net/gro_cells.h
include/net/ieee80211_radiotap.h
include/net/inet_hashtables.h
include/net/inet_sock.h
include/net/inet_timewait_sock.h
include/net/ip6_checksum.h
include/net/ip6_fib.h
include/net/ip6_route.h
include/net/ip_vs.h
include/net/ipip.h
include/net/ipv6.h
include/net/irda/irlmp.h
include/net/mac80211.h
include/net/ndisc.h
include/net/net_namespace.h
include/net/netfilter/nf_conntrack.h
include/net/netfilter/nf_nat.h
include/net/netfilter/nf_queue.h
include/net/netns/sctp.h
include/net/nfc/hci.h
include/net/nfc/nfc.h
include/net/protocol.h
include/net/request_sock.h
include/net/route.h
include/net/rtnetlink.h
include/net/sch_generic.h
include/net/sctp/command.h
include/net/sctp/constants.h
include/net/sctp/sctp.h
include/net/sctp/sm.h
include/net/sctp/structs.h
include/net/sctp/ulpqueue.h
include/net/sctp/user.h
include/net/sock.h
include/net/tcp.h
include/sound/Kbuild
include/sound/asequencer.h
include/sound/asound.h
include/sound/cs4271.h
include/sound/emu10k1.h
include/sound/pcm.h
include/sound/sb16_csp.h
include/sound/sh_fsi.h
include/sound/tlv320aic32x4.h
include/sound/vx_core.h
include/uapi/asm-generic/socket.h
include/uapi/linux/Kbuild
include/uapi/linux/ethtool.h
include/uapi/linux/filter.h
include/uapi/linux/hdlc/Kbuild
include/uapi/linux/hdlc/ioctl.h [moved from include/linux/hdlc/ioctl.h with 96% similarity]
include/uapi/linux/if_bridge.h
include/uapi/linux/if_ether.h
include/uapi/linux/if_link.h
include/uapi/linux/if_packet.h
include/uapi/linux/if_tun.h
include/uapi/linux/if_tunnel.h
include/uapi/linux/in6.h
include/uapi/linux/inet_diag.h
include/uapi/linux/input.h
include/uapi/linux/ipv6.h
include/uapi/linux/ipv6_route.h
include/uapi/linux/netconf.h [new file with mode: 0644]
include/uapi/linux/netfilter/nfnetlink_conntrack.h
include/uapi/linux/netfilter_ipv6/ip6_tables.h
include/uapi/linux/nfc.h
include/uapi/linux/nl80211.h
include/uapi/linux/pci_regs.h
include/uapi/linux/ptp_clock.h
include/uapi/linux/rtnetlink.h
include/uapi/linux/unix_diag.h
include/uapi/linux/usb/cdc.h
include/uapi/linux/virtio_net.h
include/uapi/sound/Kbuild
include/uapi/sound/asequencer.h [new file with mode: 0644]
include/uapi/sound/asound.h [new file with mode: 0644]
include/uapi/sound/asound_fm.h [moved from include/sound/asound_fm.h with 100% similarity]
include/uapi/sound/compress_offload.h [moved from include/sound/compress_offload.h with 100% similarity]
include/uapi/sound/compress_params.h [moved from include/sound/compress_params.h with 100% similarity]
include/uapi/sound/emu10k1.h [new file with mode: 0644]
include/uapi/sound/hdsp.h [moved from include/sound/hdsp.h with 100% similarity]
include/uapi/sound/hdspm.h [moved from include/sound/hdspm.h with 100% similarity]
include/uapi/sound/sb16_csp.h [new file with mode: 0644]
include/uapi/sound/sfnt_info.h [moved from include/sound/sfnt_info.h with 100% similarity]
kernel/nsproxy.c
kernel/pid.c
kernel/profile.c
kernel/time/Makefile
kernel/time/timecompare.c [deleted file]
kernel/trace/ftrace.c
kernel/trace/trace.c
kernel/trace/trace_functions.c
kernel/trace/trace_irqsoff.c
kernel/trace/trace_sched_wakeup.c
kernel/wait.c
lib/Kconfig.debug
lib/bitmap.c
mm/Kconfig
mm/hugetlb.c
mm/memory_hotplug.c
mm/page_alloc.c
mm/util.c
net/8021q/vlan.c
net/8021q/vlan_dev.c
net/atm/br2684.c
net/atm/common.c
net/atm/pppoatm.c
net/batman-adv/Kconfig
net/batman-adv/Makefile
net/batman-adv/bat_iv_ogm.c
net/batman-adv/bitarray.c
net/batman-adv/bridge_loop_avoidance.c
net/batman-adv/bridge_loop_avoidance.h
net/batman-adv/debugfs.c
net/batman-adv/distributed-arp-table.c [new file with mode: 0644]
net/batman-adv/distributed-arp-table.h [new file with mode: 0644]
net/batman-adv/gateway_client.c
net/batman-adv/hard-interface.c
net/batman-adv/hash.h
net/batman-adv/icmp_socket.c
net/batman-adv/main.c
net/batman-adv/main.h
net/batman-adv/originator.c
net/batman-adv/packet.h
net/batman-adv/routing.c
net/batman-adv/send.c
net/batman-adv/send.h
net/batman-adv/soft-interface.c
net/batman-adv/sysfs.c
net/batman-adv/translation-table.c
net/batman-adv/translation-table.h
net/batman-adv/types.h
net/batman-adv/unicast.c
net/batman-adv/unicast.h
net/batman-adv/vis.c
net/bluetooth/Kconfig
net/bluetooth/Makefile
net/bluetooth/a2mp.c
net/bluetooth/af_bluetooth.c
net/bluetooth/amp.c [new file with mode: 0644]
net/bluetooth/bnep/core.c
net/bluetooth/bnep/netdev.c
net/bluetooth/cmtp/capi.c
net/bluetooth/cmtp/core.c
net/bluetooth/cmtp/sock.c
net/bluetooth/hci_conn.c
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c
net/bluetooth/hci_sysfs.c
net/bluetooth/hidp/core.c
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_sock.c
net/bluetooth/lib.c
net/bluetooth/mgmt.c
net/bluetooth/rfcomm/core.c
net/bluetooth/rfcomm/sock.c
net/bluetooth/rfcomm/tty.c
net/bluetooth/sco.c
net/bluetooth/smp.c
net/bridge/Makefile
net/bridge/br_device.c
net/bridge/br_input.c
net/bridge/br_ioctl.c
net/bridge/br_mdb.c [new file with mode: 0644]
net/bridge/br_multicast.c
net/bridge/br_netlink.c
net/bridge/br_private.h
net/bridge/br_stp.c
net/bridge/br_stp_bpdu.c
net/bridge/br_sysfs_br.c
net/bridge/br_sysfs_if.c
net/caif/caif_usb.c
net/caif/cfctrl.c
net/can/gw.c
net/can/proc.c
net/core/dev.c
net/core/ethtool.c
net/core/filter.c
net/core/flow.c
net/core/neighbour.c
net/core/net-sysfs.c
net/core/net_namespace.c
net/core/netpoll.c
net/core/netprio_cgroup.c
net/core/pktgen.c
net/core/rtnetlink.c
net/core/scm.c
net/core/skbuff.c
net/core/sock.c
net/core/sysctl_net_core.c
net/dcb/dcbnl.c
net/dccp/minisocks.c
net/decnet/dn_dev.c
net/decnet/dn_fib.c
net/dsa/Kconfig
net/ieee802154/6lowpan.c
net/ipv4/af_inet.c
net/ipv4/arp.c
net/ipv4/devinet.c
net/ipv4/fib_frontend.c
net/ipv4/fib_semantics.c
net/ipv4/inet_connection_sock.c
net/ipv4/inet_diag.c
net/ipv4/inet_hashtables.c
net/ipv4/ip_fragment.c
net/ipv4/ip_gre.c
net/ipv4/ip_options.c
net/ipv4/ip_output.c
net/ipv4/ip_sockglue.c
net/ipv4/ip_vti.c
net/ipv4/ipconfig.c
net/ipv4/ipip.c
net/ipv4/ipmr.c
net/ipv4/netfilter/arp_tables.c
net/ipv4/netfilter/ip_tables.c
net/ipv4/netfilter/ipt_CLUSTERIP.c
net/ipv4/netfilter/iptable_nat.c
net/ipv4/protocol.c
net/ipv4/route.c
net/ipv4/syncookies.c
net/ipv4/sysctl_net_ipv4.c
net/ipv4/tcp.c
net/ipv4/tcp_cong.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_minisocks.c
net/ipv4/tcp_output.c
net/ipv4/tcp_timer.c
net/ipv6/Makefile
net/ipv6/addrconf.c
net/ipv6/af_inet6.c
net/ipv6/ah6.c
net/ipv6/anycast.c
net/ipv6/datagram.c
net/ipv6/exthdrs.c
net/ipv6/exthdrs_core.c
net/ipv6/exthdrs_offload.c [new file with mode: 0644]
net/ipv6/fib6_rules.c
net/ipv6/icmp.c
net/ipv6/inet6_hashtables.c
net/ipv6/ip6_fib.c
net/ipv6/ip6_flowlabel.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_offload.c [new file with mode: 0644]
net/ipv6/ip6_offload.h [new file with mode: 0644]
net/ipv6/ip6_output.c
net/ipv6/ip6_tunnel.c
net/ipv6/ip6mr.c
net/ipv6/ipv6_sockglue.c
net/ipv6/mcast.c
net/ipv6/ndisc.c
net/ipv6/netfilter/ip6_tables.c
net/ipv6/netfilter/ip6t_rpfilter.c
net/ipv6/netfilter/ip6table_nat.c
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
net/ipv6/netfilter/nf_nat_proto_icmpv6.c
net/ipv6/output_core.c [new file with mode: 0644]
net/ipv6/protocol.c
net/ipv6/raw.c
net/ipv6/reassembly.c
net/ipv6/route.c
net/ipv6/sit.c
net/ipv6/syncookies.c
net/ipv6/tcp_ipv6.c
net/ipv6/tcpv6_offload.c [new file with mode: 0644]
net/ipv6/udp.c
net/ipv6/udp_offload.c [new file with mode: 0644]
net/ipv6/xfrm6_policy.c
net/ipv6/xfrm6_state.c
net/key/af_key.c
net/l2tp/l2tp_netlink.c
net/llc/af_llc.c
net/mac80211/Kconfig
net/mac80211/Makefile
net/mac80211/aes_cmac.c
net/mac80211/agg-rx.c
net/mac80211/agg-tx.c
net/mac80211/cfg.c
net/mac80211/chan.c
net/mac80211/debugfs.h
net/mac80211/debugfs_key.c
net/mac80211/debugfs_netdev.c
net/mac80211/debugfs_sta.c
net/mac80211/driver-ops.h
net/mac80211/ht.c
net/mac80211/ibss.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/key.c
net/mac80211/key.h
net/mac80211/main.c
net/mac80211/mesh.c
net/mac80211/mesh.h
net/mac80211/mesh_plink.c
net/mac80211/mesh_sync.c
net/mac80211/mlme.c
net/mac80211/offchannel.c
net/mac80211/pm.c
net/mac80211/rate.c
net/mac80211/rate.h
net/mac80211/rc80211_minstrel.c
net/mac80211/rc80211_minstrel_ht.c
net/mac80211/rx.c
net/mac80211/scan.c
net/mac80211/sta_info.c
net/mac80211/sta_info.h
net/mac80211/status.c
net/mac80211/trace.h
net/mac80211/tx.c
net/mac80211/util.c
net/mac80211/vht.c [new file with mode: 0644]
net/mac80211/wme.c
net/mac80211/wpa.c
net/mac802154/tx.c
net/mac802154/wpan.c
net/netfilter/core.c
net/netfilter/ipset/ip_set_core.c
net/netfilter/ipvs/Kconfig
net/netfilter/ipvs/ip_vs_conn.c
net/netfilter/ipvs/ip_vs_core.c
net/netfilter/ipvs/ip_vs_ctl.c
net/netfilter/ipvs/ip_vs_dh.c
net/netfilter/ipvs/ip_vs_lblc.c
net/netfilter/ipvs/ip_vs_lblcr.c
net/netfilter/ipvs/ip_vs_nfct.c
net/netfilter/ipvs/ip_vs_pe_sip.c
net/netfilter/ipvs/ip_vs_proto.c
net/netfilter/ipvs/ip_vs_proto_ah_esp.c
net/netfilter/ipvs/ip_vs_proto_sctp.c
net/netfilter/ipvs/ip_vs_proto_tcp.c
net/netfilter/ipvs/ip_vs_proto_udp.c
net/netfilter/ipvs/ip_vs_sched.c
net/netfilter/ipvs/ip_vs_sh.c
net/netfilter/ipvs/ip_vs_xmit.c
net/netfilter/nf_conntrack_acct.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_ecache.c
net/netfilter/nf_conntrack_helper.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nf_conntrack_proto_dccp.c
net/netfilter/nf_conntrack_proto_tcp.c
net/netfilter/nf_conntrack_standalone.c
net/netfilter/nf_conntrack_timestamp.c
net/netfilter/nf_log.c
net/netfilter/nf_queue.c
net/netfilter/nfnetlink.c
net/netfilter/nfnetlink_queue_core.c
net/netfilter/xt_HMARK.c
net/netfilter/xt_ipvs.c
net/netlink/af_netlink.c
net/nfc/Kconfig
net/nfc/core.c
net/nfc/hci/command.c
net/nfc/hci/core.c
net/nfc/hci/llc.c
net/nfc/hci/llc_shdlc.c
net/nfc/llcp/Kconfig
net/nfc/llcp/commands.c
net/nfc/llcp/llcp.c
net/nfc/llcp/llcp.h
net/nfc/llcp/sock.c
net/nfc/nci/Kconfig
net/nfc/nci/core.c
net/nfc/netlink.c
net/nfc/nfc.h
net/nfc/rawsock.c
net/openvswitch/actions.c
net/openvswitch/datapath.c
net/openvswitch/flow.c
net/openvswitch/flow.h
net/openvswitch/vport-netdev.c
net/openvswitch/vport-netdev.h
net/openvswitch/vport.c
net/packet/af_packet.c
net/packet/internal.h
net/phonet/pn_netlink.c
net/rds/ib.h
net/rds/ib_recv.c
net/rfkill/core.c
net/rfkill/rfkill-gpio.c
net/rfkill/rfkill-regulator.c
net/sched/Kconfig
net/sched/act_api.c
net/sched/cls_api.c
net/sched/cls_cgroup.c
net/sched/sch_api.c
net/sched/sch_cbq.c
net/sched/sch_generic.c
net/sched/sch_htb.c
net/sched/sch_mq.c
net/sched/sch_mqprio.c
net/sched/sch_qfq.c
net/sctp/Kconfig
net/sctp/associola.c
net/sctp/endpointola.c
net/sctp/inqueue.c
net/sctp/ipv6.c
net/sctp/output.c
net/sctp/outqueue.c
net/sctp/proc.c
net/sctp/protocol.c
net/sctp/sm_make_chunk.c
net/sctp/sm_sideeffect.c
net/sctp/sm_statefuns.c
net/sctp/socket.c
net/sctp/sysctl.c
net/sctp/transport.c
net/sctp/tsnmap.c
net/sctp/ulpqueue.c
net/socket.c
net/sysctl_net.c
net/tipc/Kconfig
net/tipc/bcast.c
net/tipc/bearer.c
net/tipc/bearer.h
net/tipc/core.c
net/tipc/discover.c
net/tipc/link.c
net/tipc/link.h
net/tipc/name_distr.c
net/tipc/node.c
net/tipc/node.h
net/tipc/port.c
net/tipc/port.h
net/tipc/socket.c
net/tipc/subscr.c
net/unix/diag.c
net/unix/sysctl_net_unix.c
net/wireless/Kconfig
net/wireless/Makefile
net/wireless/ap.c
net/wireless/chan.c
net/wireless/core.c
net/wireless/core.h
net/wireless/ethtool.c
net/wireless/ibss.c
net/wireless/mesh.c
net/wireless/mlme.c
net/wireless/nl80211.c
net/wireless/nl80211.h
net/wireless/rdev-ops.h [new file with mode: 0644]
net/wireless/reg.c
net/wireless/reg.h
net/wireless/scan.c
net/wireless/sme.c
net/wireless/sysfs.c
net/wireless/trace.c [new file with mode: 0644]
net/wireless/trace.h [new file with mode: 0644]
net/wireless/util.c
net/wireless/wext-compat.c
net/wireless/wext-sme.c
net/xfrm/xfrm_ipcomp.c
net/xfrm/xfrm_replay.c
net/xfrm/xfrm_sysctl.c
net/xfrm/xfrm_user.c
scripts/kernel-doc
security/keys/process_keys.c
security/selinux/nlmsgtab.c
sound/arm/aaci.c
sound/arm/pxa2xx-ac97-lib.c
sound/arm/pxa2xx-ac97.c
sound/atmel/abdac.c
sound/atmel/ac97c.c
sound/core/oss/pcm_plugin.c
sound/core/pcm.c
sound/core/pcm_compat.c
sound/core/pcm_lib.c
sound/core/pcm_native.c
sound/core/seq/seq_device.c
sound/drivers/Kconfig
sound/drivers/aloop.c
sound/drivers/dummy.c
sound/drivers/ml403-ac97cr.c
sound/drivers/mpu401/mpu401.c
sound/drivers/mtpav.c
sound/drivers/mts64.c
sound/drivers/pcsp/pcsp.c
sound/drivers/pcsp/pcsp_input.c
sound/drivers/pcsp/pcsp_input.h
sound/drivers/pcsp/pcsp_lib.c
sound/drivers/pcsp/pcsp_mixer.c
sound/drivers/portman2x4.c
sound/drivers/serial-u16550.c
sound/drivers/virmidi.c
sound/drivers/vx/vx_hwdep.c
sound/firewire/Kconfig
sound/firewire/Makefile
sound/firewire/scs1x.c [new file with mode: 0644]
sound/firewire/speakers.c
sound/isa/Kconfig
sound/isa/ad1816a/ad1816a.c
sound/isa/ad1816a/ad1816a_lib.c
sound/isa/ad1848/ad1848.c
sound/isa/adlib.c
sound/isa/als100.c
sound/isa/azt2320.c
sound/isa/cmi8328.c
sound/isa/cmi8330.c
sound/isa/cs423x/cs4231.c
sound/isa/cs423x/cs4236.c
sound/isa/es1688/es1688.c
sound/isa/es18xx.c
sound/isa/galaxy/galaxy.c
sound/isa/gus/gusclassic.c
sound/isa/gus/gusextreme.c
sound/isa/gus/gusmax.c
sound/isa/gus/interwave.c
sound/isa/msnd/msnd.h
sound/isa/msnd/msnd_pinnacle.c
sound/isa/msnd/msnd_pinnacle_mixer.c
sound/isa/opl3sa2.c
sound/isa/opti9xx/miro.c
sound/isa/opti9xx/opti92x-ad1848.c
sound/isa/sb/emu8000.c
sound/isa/sb/jazz16.c
sound/isa/sb/sb16.c
sound/isa/sb/sb8.c
sound/isa/sc6000.c
sound/isa/sscape.c
sound/isa/wavefront/wavefront.c
sound/isa/wavefront/wavefront_fx.c
sound/isa/wavefront/wavefront_midi.c
sound/isa/wavefront/wavefront_synth.c
sound/mips/au1x00.c
sound/mips/hal2.c
sound/mips/sgio2audio.c
sound/oss/ad1848.c
sound/oss/kahlua.c
sound/oss/sb_audio.c
sound/parisc/harmony.c
sound/pci/Kconfig
sound/pci/ad1889.c
sound/pci/ak4531_codec.c
sound/pci/ali5451/ali5451.c
sound/pci/als300.c
sound/pci/als4000.c
sound/pci/asihpi/asihpi.c
sound/pci/asihpi/hpidspcd.c
sound/pci/asihpi/hpioctl.c
sound/pci/asihpi/hpioctl.h
sound/pci/atiixp.c
sound/pci/atiixp_modem.c
sound/pci/au88x0/au88x0.c
sound/pci/au88x0/au88x0_a3d.c
sound/pci/au88x0/au88x0_core.c
sound/pci/au88x0/au88x0_eq.c
sound/pci/au88x0/au88x0_game.c
sound/pci/au88x0/au88x0_mixer.c
sound/pci/au88x0/au88x0_mpu401.c
sound/pci/au88x0/au88x0_pcm.c
sound/pci/aw2/aw2-alsa.c
sound/pci/azt3328.c
sound/pci/bt87x.c
sound/pci/ca0106/ca0106_main.c
sound/pci/ca0106/ca0106_mixer.c
sound/pci/ca0106/ca0106_proc.c
sound/pci/ca0106/ca_midi.c
sound/pci/cmipci.c
sound/pci/cs4281.c
sound/pci/cs46xx/cs46xx.c
sound/pci/cs46xx/cs46xx_lib.c
sound/pci/cs5530.c
sound/pci/cs5535audio/cs5535audio.c
sound/pci/cs5535audio/cs5535audio.h
sound/pci/cs5535audio/cs5535audio_olpc.c
sound/pci/cs5535audio/cs5535audio_pcm.c
sound/pci/ctxfi/ctatc.c
sound/pci/ctxfi/ctatc.h
sound/pci/ctxfi/cthardware.c
sound/pci/ctxfi/cthw20k1.c
sound/pci/ctxfi/cthw20k2.c
sound/pci/ctxfi/xfi.c
sound/pci/echoaudio/echoaudio.c
sound/pci/echoaudio/echoaudio.h
sound/pci/echoaudio/midi.c
sound/pci/emu10k1/emu10k1.c
sound/pci/emu10k1/emu10k1_main.c
sound/pci/emu10k1/emu10k1_patch.c
sound/pci/emu10k1/emu10k1x.c
sound/pci/emu10k1/emufx.c
sound/pci/emu10k1/emumixer.c
sound/pci/emu10k1/emumpu401.c
sound/pci/emu10k1/emupcm.c
sound/pci/emu10k1/emuproc.c
sound/pci/emu10k1/p16v.c
sound/pci/emu10k1/timer.c
sound/pci/ens1370.c
sound/pci/es1938.c
sound/pci/es1968.c
sound/pci/fm801.c
sound/pci/hda/Kconfig
sound/pci/hda/Makefile
sound/pci/hda/hda_auto_parser.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_hwdep.c
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_intel_trace.h [new file with mode: 0644]
sound/pci/hda/hda_jack.c
sound/pci/hda/hda_jack.h
sound/pci/hda/hda_local.h
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/hda/patch_via.c
sound/pci/ice1712/Makefile
sound/pci/ice1712/amp.c
sound/pci/ice1712/aureon.c
sound/pci/ice1712/delta.c
sound/pci/ice1712/ews.c
sound/pci/ice1712/hoontech.c
sound/pci/ice1712/ice1712.c
sound/pci/ice1712/ice1712.h
sound/pci/ice1712/ice1724.c
sound/pci/ice1712/juli.c
sound/pci/ice1712/maya44.c
sound/pci/ice1712/phase.c
sound/pci/ice1712/pontis.c
sound/pci/ice1712/prodigy192.c
sound/pci/ice1712/prodigy_hifi.c
sound/pci/ice1712/psc724.c [new file with mode: 0644]
sound/pci/ice1712/psc724.h [new file with mode: 0644]
sound/pci/ice1712/quartet.c
sound/pci/ice1712/revo.c
sound/pci/ice1712/se.c
sound/pci/ice1712/vt1720_mobo.c
sound/pci/ice1712/wm8766.c [new file with mode: 0644]
sound/pci/ice1712/wm8766.h [new file with mode: 0644]
sound/pci/ice1712/wm8776.c [new file with mode: 0644]
sound/pci/ice1712/wm8776.h [new file with mode: 0644]
sound/pci/ice1712/wtm.c
sound/pci/intel8x0.c
sound/pci/intel8x0m.c
sound/pci/korg1212/korg1212.c
sound/pci/lola/lola.c
sound/pci/lola/lola_clock.c
sound/pci/lola/lola_mixer.c
sound/pci/lola/lola_pcm.c
sound/pci/lola/lola_proc.c
sound/pci/lx6464es/lx6464es.c
sound/pci/lx6464es/lx_core.c
sound/pci/lx6464es/lx_core.h
sound/pci/maestro3.c
sound/pci/mixart/mixart.c
sound/pci/mixart/mixart_hwdep.c
sound/pci/nm256/nm256.c
sound/pci/oxygen/oxygen.c
sound/pci/oxygen/virtuoso.c
sound/pci/oxygen/xonar_cs43xx.c
sound/pci/oxygen/xonar_pcm179x.c
sound/pci/oxygen/xonar_wm87x6.c
sound/pci/pcxhr/pcxhr.c
sound/pci/pcxhr/pcxhr_hwdep.c
sound/pci/riptide/riptide.c
sound/pci/rme32.c
sound/pci/rme96.c
sound/pci/rme9652/hdsp.c
sound/pci/rme9652/hdspm.c
sound/pci/rme9652/rme9652.c
sound/pci/sis7019.c
sound/pci/sonicvibes.c
sound/pci/trident/trident.c
sound/pci/trident/trident_main.c
sound/pci/via82xx.c
sound/pci/via82xx_modem.c
sound/pci/vx222/vx222.c
sound/pci/ymfpci/ymfpci.c
sound/pci/ymfpci/ymfpci_main.c
sound/ppc/awacs.c
sound/ppc/beep.c
sound/ppc/burgundy.c
sound/ppc/daca.c
sound/ppc/keywest.c
sound/ppc/pmac.c
sound/ppc/powermac.c
sound/ppc/snd_ps3.c
sound/ppc/tumbler.c
sound/sh/aica.c
sound/sh/sh_dac_audio.c
sound/soc/atmel/Kconfig
sound/soc/atmel/Makefile
sound/soc/atmel/atmel-pcm-dma.c [new file with mode: 0644]
sound/soc/atmel/atmel-pcm-pdc.c [new file with mode: 0644]
sound/soc/atmel/atmel-pcm.c
sound/soc/atmel/atmel-pcm.h
sound/soc/atmel/atmel_ssc_dai.c
sound/soc/atmel/atmel_ssc_dai.h
sound/soc/atmel/sam9g20_wm8731.c
sound/soc/au1x/ac97c.c
sound/soc/au1x/db1000.c
sound/soc/au1x/db1200.c
sound/soc/au1x/dbdma2.c
sound/soc/au1x/dma.c
sound/soc/au1x/i2sc.c
sound/soc/au1x/psc-ac97.c
sound/soc/au1x/psc-i2s.c
sound/soc/blackfin/bf5xx-ac97-pcm.c
sound/soc/blackfin/bf5xx-ac97.c
sound/soc/blackfin/bf5xx-ad1836.c
sound/soc/blackfin/bf5xx-i2s-pcm.c
sound/soc/blackfin/bf5xx-i2s.c
sound/soc/blackfin/bf5xx-tdm-pcm.c
sound/soc/blackfin/bf5xx-tdm.c
sound/soc/blackfin/bf6xx-i2s.c
sound/soc/blackfin/bfin-eval-adau1373.c
sound/soc/blackfin/bfin-eval-adau1701.c
sound/soc/blackfin/bfin-eval-adav80x.c
sound/soc/cirrus/edb93xx.c
sound/soc/cirrus/ep93xx-ac97.c
sound/soc/cirrus/ep93xx-i2s.c
sound/soc/cirrus/ep93xx-pcm.c
sound/soc/cirrus/simone.c
sound/soc/cirrus/snappercl15.c
sound/soc/codecs/88pm860x-codec.c
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile
sound/soc/codecs/ab8500-codec.c
sound/soc/codecs/ac97.c
sound/soc/codecs/ad1836.c
sound/soc/codecs/ad193x.c
sound/soc/codecs/ad1980.c
sound/soc/codecs/ad73311.c
sound/soc/codecs/adau1373.c
sound/soc/codecs/adau1701.c
sound/soc/codecs/adav80x.c
sound/soc/codecs/ads117x.c
sound/soc/codecs/ak4104.c
sound/soc/codecs/ak4535.c
sound/soc/codecs/ak4641.c
sound/soc/codecs/ak4642.c
sound/soc/codecs/ak4671.c
sound/soc/codecs/alc5623.c
sound/soc/codecs/alc5632.c
sound/soc/codecs/arizona.c
sound/soc/codecs/arizona.h
sound/soc/codecs/cq93vc.c
sound/soc/codecs/cs4271.c
sound/soc/codecs/cs42l52.c
sound/soc/codecs/cs42l73.c
sound/soc/codecs/da7210.c
sound/soc/codecs/da732x.c
sound/soc/codecs/da9055.c
sound/soc/codecs/dfbmcs320.c
sound/soc/codecs/dmic.c
sound/soc/codecs/isabelle.c
sound/soc/codecs/jz4740.c
sound/soc/codecs/lm4857.c
sound/soc/codecs/lm49453.c
sound/soc/codecs/max9768.c
sound/soc/codecs/max98088.c
sound/soc/codecs/max98090.c [new file with mode: 0644]
sound/soc/codecs/max98095.c
sound/soc/codecs/max9850.c
sound/soc/codecs/max9877.c
sound/soc/codecs/mc13783.c
sound/soc/codecs/ml26124.c
sound/soc/codecs/omap-hdmi.c
sound/soc/codecs/pcm3008.c
sound/soc/codecs/rt5631.c
sound/soc/codecs/sgtl5000.c
sound/soc/codecs/si476x.c [new file with mode: 0644]
sound/soc/codecs/sn95031.c
sound/soc/codecs/ssm2602.c
sound/soc/codecs/sta32x.c
sound/soc/codecs/sta529.c
sound/soc/codecs/stac9766.c
sound/soc/codecs/tlv320aic32x4.c
sound/soc/codecs/tlv320aic32x4.h
sound/soc/codecs/tlv320dac33.c
sound/soc/codecs/tpa6130a2.c
sound/soc/codecs/twl4030.c
sound/soc/codecs/twl6040.c
sound/soc/codecs/uda134x.c
sound/soc/codecs/uda1380.c
sound/soc/codecs/wl1273.c
sound/soc/codecs/wm0010.c
sound/soc/codecs/wm1250-ev1.c
sound/soc/codecs/wm2000.c
sound/soc/codecs/wm2200.c
sound/soc/codecs/wm5100.c
sound/soc/codecs/wm5102.c
sound/soc/codecs/wm5110.c
sound/soc/codecs/wm8350.c
sound/soc/codecs/wm8400.c
sound/soc/codecs/wm8510.c
sound/soc/codecs/wm8523.c
sound/soc/codecs/wm8711.c
sound/soc/codecs/wm8727.c
sound/soc/codecs/wm8728.c
sound/soc/codecs/wm8731.c
sound/soc/codecs/wm8737.c
sound/soc/codecs/wm8741.c
sound/soc/codecs/wm8750.c
sound/soc/codecs/wm8753.c
sound/soc/codecs/wm8770.c
sound/soc/codecs/wm8776.c
sound/soc/codecs/wm8782.c
sound/soc/codecs/wm8804.c
sound/soc/codecs/wm8900.c
sound/soc/codecs/wm8903.c
sound/soc/codecs/wm8904.c
sound/soc/codecs/wm8940.c
sound/soc/codecs/wm8955.c
sound/soc/codecs/wm8958-dsp2.c
sound/soc/codecs/wm8960.c
sound/soc/codecs/wm8961.c
sound/soc/codecs/wm8962.c
sound/soc/codecs/wm8971.c
sound/soc/codecs/wm8974.c
sound/soc/codecs/wm8978.c
sound/soc/codecs/wm8983.c
sound/soc/codecs/wm8985.c
sound/soc/codecs/wm8988.c
sound/soc/codecs/wm8990.c
sound/soc/codecs/wm8991.c
sound/soc/codecs/wm8993.c
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm8994.h
sound/soc/codecs/wm8995.c
sound/soc/codecs/wm8996.c
sound/soc/codecs/wm9081.c
sound/soc/codecs/wm9090.c
sound/soc/codecs/wm9705.c
sound/soc/codecs/wm9712.c
sound/soc/codecs/wm9713.c
sound/soc/codecs/wm_adsp.c [new file with mode: 0644]
sound/soc/codecs/wm_adsp.h [new file with mode: 0644]
sound/soc/codecs/wmfw.h [new file with mode: 0644]
sound/soc/davinci/davinci-evm.c
sound/soc/davinci/davinci-mcasp.c
sound/soc/davinci/davinci-mcasp.h
sound/soc/davinci/davinci-pcm.c
sound/soc/davinci/davinci-pcm.h
sound/soc/fsl/Kconfig
sound/soc/fsl/Makefile
sound/soc/fsl/eukrea-tlv320.c
sound/soc/fsl/fsl_dma.c
sound/soc/fsl/fsl_ssi.c
sound/soc/fsl/imx-audmux.c
sound/soc/fsl/imx-mc13783.c
sound/soc/fsl/imx-pcm-dma.c
sound/soc/fsl/imx-pcm-fiq.c
sound/soc/fsl/imx-pcm.c
sound/soc/fsl/imx-sgtl5000.c
sound/soc/fsl/imx-ssi.c
sound/soc/fsl/mpc5200_psc_ac97.c
sound/soc/fsl/mpc5200_psc_i2s.c
sound/soc/fsl/mpc8610_hpcd.c
sound/soc/fsl/mx27vis-aic32x4.c
sound/soc/fsl/p1022_ds.c
sound/soc/fsl/p1022_rdk.c [new file with mode: 0644]
sound/soc/fsl/pcm030-audio-fabric.c
sound/soc/jz4740/jz4740-i2s.c
sound/soc/jz4740/jz4740-pcm.c
sound/soc/jz4740/qi_lb60.c
sound/soc/kirkwood/kirkwood-dma.c
sound/soc/kirkwood/kirkwood-i2s.c
sound/soc/kirkwood/kirkwood-openrd.c
sound/soc/kirkwood/kirkwood-t5325.c
sound/soc/kirkwood/kirkwood.h
sound/soc/mid-x86/mfld_machine.c
sound/soc/mxs/mxs-pcm.c
sound/soc/mxs/mxs-saif.c
sound/soc/mxs/mxs-sgtl5000.c
sound/soc/nuc900/nuc900-ac97.c
sound/soc/nuc900/nuc900-pcm.c
sound/soc/omap/ams-delta.c
sound/soc/omap/mcbsp.c
sound/soc/omap/mcbsp.h
sound/soc/omap/omap-abe-twl6040.c
sound/soc/omap/omap-dmic.c
sound/soc/omap/omap-hdmi-card.c
sound/soc/omap/omap-hdmi.c
sound/soc/omap/omap-mcbsp.c
sound/soc/omap/omap-mcpdm.c
sound/soc/omap/omap-pcm.c
sound/soc/omap/omap-twl4030.c
sound/soc/omap/zoom2.c
sound/soc/pxa/brownstone.c
sound/soc/pxa/corgi.c
sound/soc/pxa/e740_wm9705.c
sound/soc/pxa/e750_wm9705.c
sound/soc/pxa/e800_wm9712.c
sound/soc/pxa/hx4700.c
sound/soc/pxa/imote2.c
sound/soc/pxa/mioa701_wm9713.c
sound/soc/pxa/mmp-pcm.c
sound/soc/pxa/mmp-sspa.c
sound/soc/pxa/palm27x.c
sound/soc/pxa/poodle.c
sound/soc/pxa/pxa-ssp.c
sound/soc/pxa/pxa2xx-ac97.c
sound/soc/pxa/pxa2xx-i2s.c
sound/soc/pxa/pxa2xx-pcm.c
sound/soc/pxa/tosa.c
sound/soc/pxa/ttc-dkb.c
sound/soc/s6000/s6000-i2s.c
sound/soc/s6000/s6000-pcm.c
sound/soc/samsung/ac97.c
sound/soc/samsung/bells.c
sound/soc/samsung/dma.c
sound/soc/samsung/dma.h
sound/soc/samsung/goni_wm8994.c
sound/soc/samsung/h1940_uda1380.c
sound/soc/samsung/i2s.c
sound/soc/samsung/idma.c
sound/soc/samsung/jive_wm8750.c
sound/soc/samsung/littlemill.c
sound/soc/samsung/ln2440sbc_alc650.c
sound/soc/samsung/lowland.c
sound/soc/samsung/neo1973_wm8753.c
sound/soc/samsung/pcm.c
sound/soc/samsung/rx1950_uda1380.c
sound/soc/samsung/s3c2412-i2s.c
sound/soc/samsung/s3c24xx-i2s.c
sound/soc/samsung/s3c24xx_simtec.c
sound/soc/samsung/s3c24xx_simtec_hermes.c
sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c
sound/soc/samsung/s3c24xx_uda134x.c
sound/soc/samsung/smartq_wm8987.c
sound/soc/samsung/smdk2443_wm9710.c
sound/soc/samsung/smdk_spdif.c
sound/soc/samsung/smdk_wm8580.c
sound/soc/samsung/smdk_wm8580pcm.c
sound/soc/samsung/smdk_wm8994.c
sound/soc/samsung/smdk_wm8994pcm.c
sound/soc/samsung/smdk_wm9713.c
sound/soc/samsung/spdif.c
sound/soc/samsung/speyside.c
sound/soc/samsung/tobermory.c
sound/soc/sh/dma-sh7760.c
sound/soc/sh/fsi.c
sound/soc/sh/hac.c
sound/soc/sh/siu_dai.c
sound/soc/sh/ssi.c
sound/soc/soc-cache.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/soc/soc-dmaengine-pcm.c
sound/soc/soc-jack.c
sound/soc/soc-pcm.c
sound/soc/soc-utils.c
sound/soc/spear/spear_pcm.c
sound/soc/tegra/tegra20_das.c
sound/soc/tegra/tegra20_i2s.c
sound/soc/tegra/tegra20_spdif.c
sound/soc/tegra/tegra30_ahub.c
sound/soc/tegra/tegra30_i2s.c
sound/soc/tegra/tegra_alc5632.c
sound/soc/tegra/tegra_pcm.c
sound/soc/tegra/tegra_wm8753.c
sound/soc/tegra/tegra_wm8903.c
sound/soc/tegra/trimslice.c
sound/soc/txx9/txx9aclc-ac97.c
sound/soc/txx9/txx9aclc.c
sound/soc/ux500/mop500.c
sound/soc/ux500/ux500_msp_dai.c
sound/soc/ux500/ux500_msp_dai.h
sound/soc/ux500/ux500_pcm.c
sound/soc/ux500/ux500_pcm.h
sound/sparc/amd7930.c
sound/sparc/cs4231.c
sound/sparc/dbri.c
sound/spi/at73c213.c
sound/usb/6fire/chip.c
sound/usb/6fire/comm.c
sound/usb/6fire/comm.h
sound/usb/6fire/control.c
sound/usb/6fire/control.h
sound/usb/6fire/firmware.h
sound/usb/6fire/midi.c
sound/usb/6fire/midi.h
sound/usb/6fire/pcm.c
sound/usb/6fire/pcm.h
sound/usb/Kconfig
sound/usb/caiaq/control.c
sound/usb/caiaq/device.c
sound/usb/card.c
sound/usb/card.h
sound/usb/endpoint.c
sound/usb/endpoint.h
sound/usb/format.c
sound/usb/midi.c
sound/usb/mixer.c
sound/usb/mixer.h
sound/usb/mixer_quirks.c
sound/usb/pcm.c
sound/usb/quirks-table.h
sound/usb/quirks.c
sound/usb/stream.c
sound/usb/usbaudio.h
tools/firewire/nosy-dump.c
tools/perf/Documentation/perf-record.txt
tools/virtio/virtio_test.c
usr/gen_init_cpio.c

index c2a270b45b03ae20084b33aa7295bdee8eb6c445..833fd59926a73c1f3725559400b60b598f2446fa 100644 (file)
@@ -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 (file)
index 0000000..4a98e02
--- /dev/null
@@ -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 (file)
index 0000000..87ac87e
--- /dev/null
@@ -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
index 7e7e07a82e0ec15dbe3255683acd67dba8d2f429..bb820be48179000dd85472ca5d02286778880aeb 100644 (file)
@@ -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 (file)
index 0000000..6349749
--- /dev/null
@@ -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.
index dff1f48d252d8f0d36aa31cccf6514cb02b3d333..1ce5ae329c048fa1f9c84523592d5bfc34c22614 100644 (file)
@@ -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.
index 38dd762def4b8fda48daf66800b93ce2666bd01d..bdc00707c751b955d997aa7ce0c51bd8b0222ca5 100644 (file)
@@ -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 (file)
index 0000000..f418c92
--- /dev/null
@@ -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.
index c81fe89c4c46d4f48e7e3bc8954d587bb9e6d69d..bc41da61608d5dfc22e0c2836aa00c56499c9d98 100644 (file)
@@ -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
index 7fc2997b23a6e25e1690249b3161a29f6b950596..9d43e76708413bdf6b3d25a0b1179714b06680ba 100644 (file)
@@ -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.
index 189dc43891bf24f57cce1806bbce0cc474763543..9eca5a182e64df28a22187ae05ff829b53de8f52 100644 (file)
@@ -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>
index 65e6e5dd67e83a04cc0f8e93feffda8eb5c7be38..7bd776f9c3c70cc2f92290cbae254a9858c41daf 100644 (file)
@@ -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
index 20f937c9d84f2ca713baaf4ef041bbaadc01da2e..a10404f15a54a510ec1dc96198363ea16b435070 100644 (file)
@@ -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 (file)
index 0000000..31c6c4c
--- /dev/null
@@ -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
index 3f8de50e4ff1dfb017da9f57befc8a568361cc71..9fa9de30d14b9a339eb6ee68f0dd4831335901d6 100644 (file)
@@ -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
index b42922cf6b1f1840965708131d7762c241df6493..f1e02a98bd9ddb179d17843ad4d865a1c884fc01 100644 (file)
@@ -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
-
index 97a003ee058bc79e444bf8e442fa87d93b8f8af3..7d1435bc976c702a7cb432a49632e7f3a6a2f6f3 100644 (file)
@@ -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/
index b02d8b8c173a9678ba8459037cddd5ab8717c05c..8a8e466eb2c01d39ec2afb7cac46cc183dde94aa 100644 (file)
@@ -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.
index cab4ec58e46e6570be19d7f343bfc5671804684f..fb32aead5a0b52a5dd72d1dbd6023472b7e1fda1 100644 (file)
   /* 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;
   }
 
   /* 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;
   }
 
   /* 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);
       <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>
 
         <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);
       components are released automatically by this call. 
       </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
   }
 
   /* 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;
           .name = KBUILD_MODNAME,
           .id_table = snd_mychip_ids,
           .probe = snd_mychip_probe,
-          .remove = __devexit_p(snd_mychip_remove),
+          .remove = snd_mychip_remove,
   };
 
   /* module initialization */
         </informalexample>
       </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
           .name = KBUILD_MODNAME,
           .id_table = snd_mychip_ids,
           .probe = snd_mychip_probe,
-          .remove = __devexit_p(snd_mychip_remove),
+          .remove = snd_mychip_remove,
   };
 ]]>
           </programlisting>
         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>
       <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>
    */
 
   /* 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;
         <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;
           ....
   }
 
-  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,
@@ -3414,13 +3394,6 @@ struct _snd_pcm_runtime {
         </example>
       </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
@@ -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,
index 59c080f084ef3dcfb52a21e850334b66672fe6af..a9f288ff54f97214c3afd4fd10839a4e75de01ad 100644 (file)
@@ -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."
index fc73ef5d65b81366360d9d213bc2d675875ad4b7..cfaca7e6989346246e3205c52a353ea960b50ce5 100644 (file)
@@ -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,
 };
index 6f706aca2049718c436501f56b8e33592f7f14d6..f8ebcde43b174640ae1ab1d8ac47426a10688614 100644 (file)
@@ -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 (file)
index 0000000..cc9ce57
--- /dev/null
@@ -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).
index 6528e215c5fe54e3c7e74ba2f909342e3773b635..5216b419016aa7065e618285047b44ab0b033e1e 100644 (file)
@@ -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>;
+               /* ... */
+       };
index ac9e7516756e62a3817d1b9ac8338c1f47a45440..f79818711e83c8b3905a997f4d9c0a36e55b883a 100644 (file)
@@ -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 (file)
index 0000000..37824fa
--- /dev/null
@@ -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 (file)
index 0000000..0849f10
--- /dev/null
@@ -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 (file)
index 0000000..c2a3525
--- /dev/null
@@ -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 (file)
index 0000000..23ae1db
--- /dev/null
@@ -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 (file)
index 0000000..589edee
--- /dev/null
@@ -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 (file)
index 0000000..fa166d9
--- /dev/null
@@ -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 (file)
index 0000000..858f4f9
--- /dev/null
@@ -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 (file)
index 0000000..9b2ea03
--- /dev/null
@@ -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 (file)
index 0000000..558cdf3
--- /dev/null
@@ -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 (file)
index 0000000..9c27ed6
--- /dev/null
@@ -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 (file)
index 0000000..ca5a2c8
--- /dev/null
@@ -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 (file)
index 0000000..67ec3d4
--- /dev/null
@@ -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 (file)
index 0000000..38e51ad
--- /dev/null
@@ -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 (file)
index 0000000..34ef349
--- /dev/null
@@ -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 (file)
index 0000000..09055c2
--- /dev/null
@@ -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];
+       };
index dcaabe9fe869d7f029f413d6d97335549974fd05..6ddd0286a9b7514fe00a5f150e05859da0f25e36 100644 (file)
@@ -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 ];
                };
index 361bccb7ec89bad6f23eca65a44a98466fa712ea..95daf6335c3796e2256ddb94e3e21190cf0c1b35 100644 (file)
@@ -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 (file)
index 0000000..63c6598
--- /dev/null
@@ -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 (file)
index 0000000..0057695
--- /dev/null
@@ -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 (file)
index 0000000..9fd69a1
--- /dev/null
@@ -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 (file)
index 0000000..d775f72
--- /dev/null
@@ -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 (file)
index 0000000..93f45e9
--- /dev/null
@@ -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 (file)
index 0000000..b902ee3
--- /dev/null
@@ -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 (file)
index 0000000..9c5a994
--- /dev/null
@@ -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>;
+};
index c81b5fd5a5bc80459a1b2d626c9f20b5a86bfbe9..a850fb9c88eab2156ec89f0c76d8ca59073540f8 100644 (file)
@@ -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:
 
index 65dec876cb2d792813abc050833950ef48b53a66..fd40c852d7c7e18c12e5fabc49f0b141614267ac 100644 (file)
@@ -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 (file)
index 0000000..e019fdc
--- /dev/null
@@ -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 (file)
index 0000000..906109d
--- /dev/null
@@ -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 (file)
index 0000000..6bc09ec
--- /dev/null
@@ -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>;
+       };
index 770a0193ca1b21280749b7a66ce782312ac5842b..902b1b1f568e39b16a26e0ca6278f9225ea1fd9e 100644 (file)
@@ -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 (file)
index 0000000..2957ebb
--- /dev/null
@@ -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>;
+       };
index ad86fb86c9a0252ba7c51df8d5ddcf91d71eb6ed..0188903bc9e1ede2c5668d5d78c632d2c4f923b3 100644 (file)
@@ -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
index 74c25c8d8884633c7275b590a48a229482685bbd..b89a739a32761db0f9100395fd6426352ad9167c 100644 (file)
@@ -181,7 +181,6 @@ modversions.h*
 nconf
 ncscope.*
 offset.h
-offsets.h
 oui.c*
 page-types
 parse.c
index c83526c364e58433ec96023d5e8fa4deeebe9f95..09adabef513ff863ae6f413a239b0b79f90d575b 100644 (file)
@@ -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
index 4627c4241ece699cedbe6660c7754e12933c4c2c..3c741214dfbbb028044be22a88c5359f7ba49646 100644 (file)
@@ -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.
 
index f90f99920cc5ea49664aa1c6ed334f1619cbd94c..3d3a0f97f966f677e76a5d9685036edc43022ca6 100644 (file)
@@ -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 (file)
index 0000000..557d6d5
--- /dev/null
@@ -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.
index ae8ba9a74ce13e68519c2afa535c4cd06a4827db..3262b6e4d686ac944f7e767642228f4d4cc2f8f6 100644 (file)
@@ -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.
 
index 53305bd08182dac8db030112ed9dadf1bf99efc9..f1ea2c69648dcad46d061a78ac33036d3ac5c727 100644 (file)
@@ -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
index 3fb39e0116b4c8e42d40009357ed5cf13c1f2888..69372fb98cf89e4971e1520cd335ff66f27f7a6f 100644 (file)
@@ -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
index 3d8a97747f7731c801ca7d3a1483858feeb76b6c..99b57abddf8a186e2dcb399e167778c3605147df 100644 (file)
@@ -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
index 28bd0f0e32c517359c946029fc814c9cc0d4a474..20e248cc03a9a64f08f55af30d10f8fe328c6861 100644 (file)
@@ -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.
index 01804f21631293b796a113319c202d2593330b5e..49e4f770864a5f1ee2211e75378719f39e91eafd 100644 (file)
@@ -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 {
index a173d2a879f5cf7619b221148edbbac4789bbe8a..c1d82047a4b151c35983656e5841e261ff22fd7f 100644 (file)
@@ -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.
index c7fc10724948629c98100b19250f8ee07d9dcd73..dd52d516cb8902da098bbb21a5006cea81b66a74 100644 (file)
@@ -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
index 1c08a4b0981fb7f648cee60ffea8b3c45bb319c4..94444b152fbcc7d56a3549a3578ededb357cf956 100644 (file)
@@ -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:
 
@@ -493,6 +494,196 @@ The user can also use poll() to check if a buffer is available:
     pfd.events = POLLOUT;
     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
 --------------------------------------------------------------------------------
index ef9ee71b4d7fcc71a38dc94454828e74a606cded..f9fa6db40a5291155d4f39141d82f89b46d0c0b5 100644 (file)
@@ -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 .
index d90d8ec2853df3e49e18edefc1bffd8995826403..b9cfd339a6fa3d4e89cebb3316e5152f9ff0d252 100644 (file)
@@ -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.
index db833ced2cb89cc68d9fa9c10c400cbdb64e056a..a8fb6e2d3c8bed16d0f32930ac6ba0006c7fa64a 100644 (file)
@@ -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!!!
 
 
 
index 395f6c6fdd9899883e6e8a75ed7ae517a2efac62..d3f1d7783d1ccde25d42e496a69165244dee8728 100644 (file)
@@ -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.
index 5ef2d1366425416128d252fab11f884350a758fc..c71a019be600bf7f7d54f1917cba50059bb9cdf6 100644 (file)
@@ -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
index 386fce6715c458e75e492b8fd0ca5ca76ca91cae..b0b880da6e5c0e57c932c21f72e0025f2bc6435b 100644 (file)
@@ -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 f32710a817fc392262f5f890cb637e5e0b1b5d1a..a24ec89ba4420ad38e8848422ca5f69baa5ffe1c 100644 (file)
--- 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,
index 445dc42e033495be2ac6b1ae37fe3a8221c483e8..c5b5d6bac9ed1ac42b93275cf0602200ddf479f5 100644 (file)
@@ -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)
index 7d2f75be932e6d16e4ceba058fe0e0c769a8be32..0087d053b77f9ada256b4d58fec451552d48eb63 100644 (file)
@@ -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
index 3f844d26d2c71e072d28fb71a232e444daba281b..a21d0ab3b19e1cf3f57f7c95e2a0b5dbe4ab8e9d 100644 (file)
@@ -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;
index 08330d9e6a9cffd37ad628fe28f992eb0250d37c..2277f9530b0078886b052306d76452b268014e67 100644 (file)
@@ -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
index 04a3f0d1d053bb44effecc8a045818e1b915fb36..661030d6bc6c3d10f3ca35f6b8125d21adac7389 100644 (file)
@@ -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
index 9c60f474a5594d5b5db10c880842f35e5889c0ae..30c443c406f3f85ef6f473b7522d426716f56ba6 100644 (file)
@@ -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
index f3f2f80cdf3b686708d17f60b72c9e77076cea92..2af359cfe985bec9d996303be88336b32099bb78 100644 (file)
@@ -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
index 2c338889df1bd308e8e76da28148a0434a830ca0..11b240c5d3238e7a76699be74f0f1085de4f5c4b 100644 (file)
                };
        };
 };
+
+&cpsw_emac0 {
+       phy_id = <&davinci_mdio>, <0>;
+};
+
+&cpsw_emac1 {
+       phy_id = <&davinci_mdio>, <1>;
+};
index 9f65f17ebdf8f10452e28048a9c7a7af5a8e455c..d6496440fcea496b2d93a3b91b8005101ccc2efa 100644 (file)
                };
        };
 };
+
+&cpsw_emac0 {
+       phy_id = <&davinci_mdio>, <0>;
+};
+
+&cpsw_emac1 {
+       phy_id = <&davinci_mdio>, <1>;
+};
index 20a3f29a6bfeaf9a81b4c988b64dbe8ab3aa16cb..c2f14e875eb6274b18fc159e8e773395aca6df87 100644 (file)
                        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 ];
+                       };
+               };
        };
 };
index b1d3fab60e0a9bf7df64de7cb1adcc45daaa95fa..68bccf41a2c6a1855c6dfd87555faabf81306cb7 100644 (file)
@@ -29,6 +29,7 @@
                tcb0 = &tcb0;
                tcb1 = &tcb1;
                i2c0 = &i2c0;
+               ssc0 = &ssc0;
        };
        cpus {
                cpu@0 {
                                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>;
                                        trigger-external;
                                };
                        };
+
+                       watchdog@fffffd40 {
+                               compatible = "atmel,at91sam9260-wdt";
+                               reg = <0xfffffd40 0x10>;
+                               status = "disabled";
+                       };
                };
 
                nand0: nand@40000000 {
index 66106eecf1ed9e912ae6b34ad90085f698837559..8e6251f1f7a3d9ee36008f4ad9ee73b49f2e3cd9 100644 (file)
@@ -25,6 +25,8 @@
                gpio4 = &pioE;
                tcb0 = &tcb0;
                i2c0 = &i2c0;
+               ssc0 = &ssc0;
+               ssc1 = &ssc1;
        };
        cpus {
                cpu@0 {
                                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>;
                                #size-cells = <0>;
                                status = "disabled";
                        };
+
+                       watchdog@fffffd40 {
+                               compatible = "atmel,at91sam9260-wdt";
+                               reg = <0xfffffd40 0x10>;
+                               status = "disabled";
+                       };
                };
 
                nand0: nand@40000000 {
index 32a500a0e481f7473de51be152546081b8bddd15..da15e83e7f179deceb146b19e5d3b8d7ddb8e90d 100644 (file)
 
        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";
                        };
                                        };
                                };
                        };
+
+                       ssc0: ssc@fffbc000 {
+                               status = "okay";
+                               pinctrl-0 = <&pinctrl_ssc0_tx>;
+                       };
                };
 
                nand0: nand@40000000 {
                        reg = <0x50>;
                };
 
-               wm8731@1b {
+               wm8731: wm8731@1b {
                        compatible = "wm8731";
                        reg = <0x1b>;
                };
                        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>;
+       };
 };
index 0741caeeced1a5618950e1c9a299578ad2b2ba3d..fa1ae0c5479c0480022fac86fe576806154da73e 100644 (file)
@@ -31,6 +31,8 @@
                tcb1 = &tcb1;
                i2c0 = &i2c0;
                i2c1 = &i2c1;
+               ssc0 = &ssc0;
+               ssc1 = &ssc1;
        };
        cpus {
                cpu@0 {
                                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>;
                                #size-cells = <0>;
                                status = "disabled";
                        };
+
+                       watchdog@fffffd40 {
+                               compatible = "atmel,at91sam9260-wdt";
+                               reg = <0xfffffd40 0x10>;
+                               status = "disabled";
+                       };
                };
 
                nand0: nand@40000000 {
index 7ee49e8daf987af65060b8b058f8b29a6ff2e6d0..617ede541ca273b76d7ca6961c6cbd6273073c3d 100644 (file)
@@ -30,6 +30,7 @@
                i2c0 = &i2c0;
                i2c1 = &i2c1;
                i2c2 = &i2c2;
+               ssc0 = &ssc0;
        };
        cpus {
                cpu@0 {
                                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 (file)
index 0000000..0430546
--- /dev/null
@@ -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 (file)
index 0000000..fddd174
--- /dev/null
@@ -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;
+               };
+       };
+};
index 731086b2fca221ec61aab7fd020d52cf475ff36f..0d69322f689f03bbe16b1d061d33cd847ced989f 100644 (file)
                                // 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";
                                };
                        };
 
                                        // 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;
                                        // 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>;
                                        };
                                        // 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>;
                                        };
                                        // 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";
                                        };
                                };
                        };
                        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>;
                        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";
+               };
        };
 };
index 0adbd5a38095fb8340253ea351d4156d2993b0cf..fed7d3f9f431071af027d72a12c92dcb6f365943 100644 (file)
                reg = <0>;
        };
 };
+
+&pinctrl {
+       pinctrl-0 = <&pmx_gpio_18>;
+       pinctrl-names = "default";
+
+       pmx_gpio_18: pmx-gpio-18 {
+               marvell,pins = "mpp18";
+               marvell,function = "gpio";
+       };
+};
index 5a00022383e74d7e457c34be0331eb3edf7c0521..61f391412a5a60cd3ae310c9576d057df97f9e98 100644 (file)
@@ -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>;
                };
 
                        #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 {
index b7354e6506de9febf50bca6727b08912bdd75e6e..96e50f569433850ca54a941c4fd3a6fe4a17eafd 100644 (file)
                                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 {
index 96d4462730fbe18353c62aa579213516abd965b7..e1347fceb5bc44c269e62d85c97a36249a76a073 100644 (file)
                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 {
                status = "disabled";
        };
 
-       i2c@13860000 {
+       i2c_0: i2c@13860000 {
                #address-cells = <1>;
                #size-cells = <0>;
                compatible = "samsung,s3c2440-i2c";
                status = "disabled";
        };
 
-       i2c@13870000 {
+       i2c_1: i2c@13870000 {
                #address-cells = <1>;
                #size-cells = <0>;
                compatible = "samsung,s3c2440-i2c";
                status = "disabled";
        };
 
-       i2c@13880000 {
+       i2c_2: i2c@13880000 {
                #address-cells = <1>;
                #size-cells = <0>;
                compatible = "samsung,s3c2440-i2c";
                status = "disabled";
        };
 
-       i2c@13890000 {
+       i2c_3: i2c@13890000 {
                #address-cells = <1>;
                #size-cells = <0>;
                compatible = "samsung,s3c2440-i2c";
                status = "disabled";
        };
 
-       i2c@138A0000 {
+       i2c_4: i2c@138A0000 {
                #address-cells = <1>;
                #size-cells = <0>;
                compatible = "samsung,s3c2440-i2c";
                status = "disabled";
        };
 
-       i2c@138B0000 {
+       i2c_5: i2c@138B0000 {
                #address-cells = <1>;
                #size-cells = <0>;
                compatible = "samsung,s3c2440-i2c";
                status = "disabled";
        };
 
-       i2c@138C0000 {
+       i2c_6: i2c@138C0000 {
                #address-cells = <1>;
                #size-cells = <0>;
                compatible = "samsung,s3c2440-i2c";
                status = "disabled";
        };
 
-       i2c@138D0000 {
+       i2c_7: i2c@138D0000 {
                #address-cells = <1>;
                #size-cells = <0>;
                compatible = "samsung,s3c2440-i2c";
index 3e68f52e8454431d90c5bd1d47de5b791ce56b2e..f2710018e84eca2cb758825d84a6f8acde45ea60 100644 (file)
        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";
        };
 
 
                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;
                };
        leds {
                compatible = "gpio-leds";
                status {
-                       gpios = <&gpx1 3 0 0x10000 2>;
+                       gpios = <&gpx1 3 1>;
                        linux,default-trigger = "heartbeat";
                };
        };
index 6a4a1a04221c316b2b4ca9ab95f2179b17bbb7a4..55a2efb763d1c014fb5d06804abea8bc67fa382d 100644 (file)
                        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 {
index 63610c3ba3afbeffbeee894d2ea75e3b8ed24709..9b23a8255e39a148eecdd18e04391f4a2f6529f0 100644 (file)
                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>;
index a21511c140712e24c4759293ac66248bbb8ae309..c346b64dff552ef3d13599846130f63be9068e5e 100644 (file)
                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";
        };
                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 {
                        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>,
index d877dbe7ac0e767c020e2b8bf63ebe7566a8aa65..e31bfc4a6f097233fa5e20fa870726d302c4b3a4 100644 (file)
                pinctrl2 = &pinctrl_2;
        };
 
+       pd_lcd1: lcd1-power-domain@10023CA0 {
+               compatible = "samsung,exynos4210-pd";
+               reg = <0x10023CA0 0x20>;
+       };
+
        gic:interrupt-controller@10490000 {
                cpu-offset = <0x8000>;
        };
                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 (file)
index 0000000..c6ae200
--- /dev/null
@@ -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 (file)
index 0000000..f05bf57
--- /dev/null
@@ -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 (file)
index 0000000..d7dfe31
--- /dev/null
@@ -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 (file)
index 0000000..8e6115a
--- /dev/null
@@ -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 (file)
index 0000000..179a62e
--- /dev/null
@@ -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>;
+       };
+};
index a352df403b7a5586ad1b2a47cb51c9eca0e89b0e..942d5761ca971dd7317c8398d5ddaddd0b0fce98 100644 (file)
        compatible = "samsung,smdk5250", "samsung,exynos5250";
 
        aliases {
-               mshc0 = &dwmmc_0;
-               mshc1 = &dwmmc_1;
-               mshc2 = &dwmmc_2;
-               mshc3 = &dwmmc_3;
        };
 
        memory {
                };
        };
 
+       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 {
                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;
                };
        };
 
-       dwmmc_1: dwmmc1@12210000 {
+       dwmmc1@12210000 {
                status = "disabled";
        };
 
-       dwmmc_2: dwmmc2@12220000 {
+       dwmmc2@12220000 {
                num-slots = <1>;
                supports-highspeed;
                fifo-depth = <0x80>;
                };
        };
 
-       dwmmc_3: dwmmc3@12230000 {
+       dwmmc3@12230000 {
                status = "disabled";
        };
 
        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 (file)
index 0000000..17dd951
--- /dev/null
@@ -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>;
+               };
+       };
+};
index dddfd6e444dcb1edbcb1d6f94617e6d29f87e5c7..36d8246ea50eaef5e5cae9c719b8ade854a17bd1 100644 (file)
                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 {
                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>;
                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>;
                #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>;
                #size-cells = <0>;
        };
 
-       dwmmc0@12200000 {
+       dwmmc_0: dwmmc0@12200000 {
                compatible = "samsung,exynos5250-dw-mshc";
                reg = <0x12200000 0x1000>;
                interrupts = <0 75 0>;
                #size-cells = <0>;
        };
 
-       dwmmc1@12210000 {
+       dwmmc_1: dwmmc1@12210000 {
                compatible = "samsung,exynos5250-dw-mshc";
                reg = <0x12210000 0x1000>;
                interrupts = <0 76 0>;
                #size-cells = <0>;
        };
 
-       dwmmc2@12220000 {
+       dwmmc_2: dwmmc2@12220000 {
                compatible = "samsung,exynos5250-dw-mshc";
                reg = <0x12220000 0x1000>;
                interrupts = <0 77 0>;
                #size-cells = <0>;
        };
 
-       dwmmc3@12230000 {
+       dwmmc_3: dwmmc3@12230000 {
                compatible = "samsung,exynos5250-dw-mshc";
                reg = <0x12230000 0x1000>;
                interrupts = <0 78 0>;
                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 (file)
index 0000000..592fb9d
--- /dev/null
@@ -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 (file)
index 0000000..eec29c4
--- /dev/null
@@ -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";
+               };
+       };
+};
index 2131d77dc9c924adc0c8a0062e552a644dd542d6..55f4191a626ede9b0f74d27752ede38d7a547b2b 100644 (file)
 
 /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";
+                                       };
+                               };
+                       };
                };
        };
 };
index 384d8b66f337e1ceec0388a9e49e6eeae5ffadce..7c43b8e70b9fcb1c29da27a059f658440ddec246 100644 (file)
                                        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>;
                                        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 {
 
        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>;
                };
        };
 };
index 6d31aa3834608d41d84d848ec954f00a064a4659..65415c598a5e53bad0837044c5ee1326c7329f5f 100644 (file)
                                        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 (file)
index 0000000..d81f8a0
--- /dev/null
@@ -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 (file)
index 0000000..e1b13eb
--- /dev/null
@@ -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 (file)
index 0000000..c0327c0
--- /dev/null
@@ -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>;
+                       };
+               };
+       };
+};
index 67d672792b0ddd1c8ea48bf5df4a309d48aa04ae..b8d3905915acaf7a296e880cbcfee0023e8b1da3 100644 (file)
@@ -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>;
                                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 (file)
index 0000000..7eb0758
--- /dev/null
@@ -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 (file)
index 0000000..6d8865b
--- /dev/null
@@ -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>;
+       };
+};
index c03a577beca3845af06b4613abcdafa785555d5a..1594694532b96d845507d2700b3613dca5020b6d 100644 (file)
 
        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";
                };
 
                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>;
index 05c892e931e31521b462f2b0075bc20b00d4511e..b222614ac9e0d3ac2dac19b330f23bed7db02380 100644 (file)
        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>;
                                        spi-max-frequency = <100000>;
                                };
 
+                               dac0: dh2228@2 {
+                                       compatible = "rohm,dh2228fv";
+                                       reg = <2>;
+                                       spi-max-frequency = <100000>;
+                               };
                        };
                };
 
                        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";
+               };
+       };
 };
index a0ad71ca3a4402a40c39d5a2d2050208cf9d6089..2da316e04409f103c44fcf4ff35fe5dc48a93924 100644 (file)
@@ -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 */
                                        >;
                                        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 = <
 
        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 (file)
index 0000000..e6cde8a
--- /dev/null
@@ -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>;
+               };
+
+       };
+};
index b4587b27ae424934d696281801fdf8c029e74704..13b7053d799ed0b927ad9c9d897270f6e2ac5094 100644 (file)
                                        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 = <
                                        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 = <
index 2781e47cff0d96bce5b2eab2dc394c9a8a730646..1f5d45eff45e25be4ec0ff027c044b1526a5d65e 100644 (file)
@@ -83,7 +83,7 @@
                                reg = <0x70000000 0x40000>;
                                ranges;
 
-                               esdhc@70004000 { /* ESDHC1 */
+                               esdhc1: esdhc@70004000 {
                                        compatible = "fsl,imx51-esdhc";
                                        reg = <0x70004000 0x4000>;
                                        interrupts = <1>;
                                        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";
                                };
 
                                        status = "disabled";
                                };
 
-                               ecspi@70010000 { /* ECSPI1 */
+                               ecspi1: ecspi@70010000 {
                                        #address-cells = <1>;
                                        #size-cells = <0>;
                                        compatible = "fsl,imx51-ecspi";
                                        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>;
                                #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>;
                                status = "disabled";
                        };
 
-                       iomuxc@73fa8000 {
+                       iomuxc: iomuxc@73fa8000 {
                                compatible = "fsl,imx51-iomuxc";
                                reg = <0x73fa8000 0x4000>;
 
                        reg = <0x80000000 0x10000000>;
                        ranges;
 
-                       ecspi@83fac000 { /* ECSPI2 */
+                       ecspi2: ecspi@83fac000 {
                                #address-cells = <1>;
                                #size-cells = <0>;
                                compatible = "fsl,imx51-ecspi";
                                status = "disabled";
                        };
 
-                       sdma@83fb0000 {
+                       sdma: sdma@83fb0000 {
                                compatible = "fsl,imx51-sdma", "fsl,imx35-sdma";
                                reg = <0x83fb0000 0x4000>;
                                interrupts = <6>;
                                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";
                                status = "disabled";
                        };
 
-                       i2c@83fc4000 { /* I2C2 */
+                       i2c2: i2c@83fc4000 {
                                #address-cells = <1>;
                                #size-cells = <0>;
                                compatible = "fsl,imx51-i2c", "fsl,imx21-i2c";
                                status = "disabled";
                        };
 
-                       i2c@83fc8000 { /* I2C1 */
+                       i2c1: i2c@83fc8000 {
                                #address-cells = <1>;
                                #size-cells = <0>;
                                compatible = "fsl,imx51-i2c", "fsl,imx21-i2c";
                                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>;
                                status = "disabled";
                        };
 
-                       ethernet@83fec000 {
+                       fec: ethernet@83fec000 {
                                compatible = "fsl,imx51-fec", "fsl,imx27-fec";
                                reg = <0x83fec000 0x4000>;
                                interrupts = <87>;
index 08948af86d1a096611465ab453755e0636fa3e2d..b0075537195bda29f5a19ef232c4d5d9b2c3a2f6 100644 (file)
                                                        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 {
                                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;
                                                };
                                        };
                                };
 
        leds {
                compatible = "gpio-leds";
+               pinctrl-names = "default";
+               pinctrl-0 = <&led_pin_gpio7_7>;
 
                user {
                        label = "Heartbeat";
index da9a047ce4cf29049a8ada0d262b8b685e731b3e..552aed4ff9823e63bdfdca1df059cff82b7f2baa 100644 (file)
                                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";
                                };
 
                                        status = "disabled";
                                };
 
-                               ecspi@50010000 { /* ECSPI1 */
+                               ecspi1: ecspi@50010000 {
                                        #address-cells = <1>;
                                        #size-cells = <0>;
                                        compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi";
                                        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>;
                                #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>;
                                status = "disabled";
                        };
 
-                       iomuxc@53fa8000 {
+                       iomuxc: iomuxc@53fa8000 {
                                compatible = "fsl,imx53-iomuxc";
                                reg = <0x53fa8000 0x4000>;
 
                                        };
                                };
 
+                               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 = <
                                        };
                                };
 
+                               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 = <
                                                >;
                                        };
                                };
+
+                               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 {
                                #interrupt-cells = <2>;
                        };
 
-                       i2c@53fec000 { /* I2C3 */
+                       i2c3: i2c@53fec000 {
                                #address-cells = <1>;
                                #size-cells = <0>;
                                compatible = "fsl,imx53-i2c", "fsl,imx21-i2c";
                                status = "disabled";
                        };
 
-                       ecspi@63fac000 { /* ECSPI2 */
+                       ecspi2: ecspi@63fac000 {
                                #address-cells = <1>;
                                #size-cells = <0>;
                                compatible = "fsl,imx53-ecspi", "fsl,imx51-ecspi";
                                status = "disabled";
                        };
 
-                       sdma@63fb0000 {
+                       sdma: sdma@63fb0000 {
                                compatible = "fsl,imx53-sdma", "fsl,imx35-sdma";
                                reg = <0x63fb0000 0x4000>;
                                interrupts = <6>;
                                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";
                                status = "disabled";
                        };
 
-                       i2c@63fc4000 { /* I2C2 */
+                       i2c2: i2c@63fc4000 {
                                #address-cells = <1>;
                                #size-cells = <0>;
                                compatible = "fsl,imx53-i2c", "fsl,imx21-i2c";
                                status = "disabled";
                        };
 
-                       i2c@63fc8000 { /* I2C1 */
+                       i2c1: i2c@63fc8000 {
                                #address-cells = <1>;
                                #size-cells = <0>;
                                compatible = "fsl,imx53-i2c", "fsl,imx21-i2c";
                                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>;
                                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 (file)
index 0000000..826e4ad
--- /dev/null
@@ -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";
+                       };
+               };
+       };
+};
index e596c28c214d22fcabb237cef02239664a2cb0e4..a42402562b7b55a4b0f67dab681faf812ac4b1c5 100644 (file)
@@ -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 */
                        };
                };
        };
+
+       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 */
+               };
+       };
 };
index d907d062e5dd36416d6e063c2c590da29a0642b4..d6265ca971190b06b2217199d4d98321ddb2d6d8 100644 (file)
                        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 {
                        clocks = <&clks 106>;
                };
 
-               gpmi-nand@00112000 {
+               nfc: gpmi-nand@00112000 {
                        compatible = "fsl,imx6q-gpmi-nand";
                        #address-cells = <1>;
                        #size-cells = <1>;
                                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";
                                        status = "disabled";
                                };
 
-                               ecspi@0200c000 { /* eCSPI2 */
+                               ecspi2: ecspi@0200c000 {
                                        #address-cells = <1>;
                                        #size-cells = <0>;
                                        compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
                                        status = "disabled";
                                };
 
-                               ecspi@02010000 { /* eCSPI3 */
+                               ecspi3: ecspi@02010000 {
                                        #address-cells = <1>;
                                        #size-cells = <0>;
                                        compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
                                        status = "disabled";
                                };
 
-                               ecspi@02014000 { /* eCSPI4 */
+                               ecspi4: ecspi@02014000 {
                                        #address-cells = <1>;
                                        #size-cells = <0>;
                                        compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
                                        status = "disabled";
                                };
 
-                               ecspi@02018000 { /* eCSPI5 */
+                               ecspi5: ecspi@02018000 {
                                        #address-cells = <1>;
                                        #size-cells = <0>;
                                        compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
                                        status = "disabled";
                                };
 
-                               esai@02024000 {
+                               esai: esai@02024000 {
                                        reg = <0x02024000 0x4000>;
                                        interrupts = <0 51 0x04>;
                                };
                                        status = "disabled";
                                };
 
-                               asrc@02034000 {
+                               asrc: asrc@02034000 {
                                        reg = <0x02034000 0x4000>;
                                        interrupts = <0 50 0x04>;
                                };
                                };
                        };
 
-                       vpu@02040000 {
+                       vpu: vpu@02040000 {
                                reg = <0x02040000 0x3c000>;
                                interrupts = <0 3 0x04 0 12 0x04>;
                        };
                                reg = <0x0207c000 0x4000>;
                        };
 
-                       pwm@02080000 { /* PWM1 */
+                       pwm1: pwm@02080000 {
                                #pwm-cells = <2>;
                                compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
                                reg = <0x02080000 0x4000>;
                                clock-names = "ipg", "per";
                        };
 
-                       pwm@02084000 { /* PWM2 */
+                       pwm2: pwm@02084000 {
                                #pwm-cells = <2>;
                                compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
                                reg = <0x02084000 0x4000>;
                                clock-names = "ipg", "per";
                        };
 
-                       pwm@02088000 { /* PWM3 */
+                       pwm3: pwm@02088000 {
                                #pwm-cells = <2>;
                                compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
                                reg = <0x02088000 0x4000>;
                                clock-names = "ipg", "per";
                        };
 
-                       pwm@0208c000 { /* PWM4 */
+                       pwm4: pwm@0208c000 {
                                #pwm-cells = <2>;
                                compatible = "fsl,imx6q-pwm", "fsl,imx27-pwm";
                                reg = <0x0208c000 0x4000>;
                                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>;
                                #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>;
                                        anatop-max-voltage = <2750000>;
                                };
 
-                               regulator-vddcore@140 {
+                               reg_cpu: regulator-vddcore@140 {
                                        compatible = "fsl,anatop-regulator";
                                        regulator-name = "cpu";
                                        regulator-min-microvolt = <725000>;
                        };
 
                        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>;
                                reg = <0x020e0000 0x38>;
                        };
 
-                       iomuxc@020e0000 {
+                       iomuxc: iomuxc@020e0000 {
                                compatible = "fsl,imx6q-iomuxc";
                                reg = <0x020e0000 0x4000>;
 
                                                        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*/
                                                >;
                                        };
 
                                };
                        };
 
-                       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>;
                                reg = <0x0217c000 0x4000>;
                        };
 
-                       usb@02184000 { /* USB OTG */
+                       usbotg: usb@02184000 {
                                compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
                                reg = <0x02184000 0x200>;
                                interrupts = <0 43 0x04>;
                                status = "disabled";
                        };
 
-                       usb@02184200 { /* USB1 */
+                       usbh1: usb@02184200 {
                                compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
                                reg = <0x02184200 0x200>;
                                interrupts = <0 40 0x04>;
                                status = "disabled";
                        };
 
-                       usb@02184400 { /* USB2 */
+                       usbh2: usb@02184400 {
                                compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
                                reg = <0x02184400 0x200>;
                                interrupts = <0 41 0x04>;
                                status = "disabled";
                        };
 
-                       usb@02184600 { /* USB3 */
+                       usbh3: usb@02184600 {
                                compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
                                reg = <0x02184600 0x200>;
                                interrupts = <0 42 0x04>;
                                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";
                        };
 
                                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";
                                status = "disabled";
                        };
 
-                       i2c@021a4000 { /* I2C2 */
+                       i2c2: i2c@021a4000 {
                                #address-cells = <1>;
                                #size-cells = <0>;
                                compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
                                status = "disabled";
                        };
 
-                       i2c@021a8000 { /* I2C3 */
+                       i2c3: i2c@021a8000 {
                                #address-cells = <1>;
                                #size-cells = <0>;
                                compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
                                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>;
                        };
 
                                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 (file)
index 0000000..d6c9d65
--- /dev/null
@@ -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 (file)
index 0000000..9ae2004
--- /dev/null
@@ -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 (file)
index 0000000..3271e4c
--- /dev/null
@@ -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";
+                       };
+               };
+       };
+};
index 9b32d0272825fcb172c0ef720c30f74c4202e0f5..6875ac00c17437c51a0e31c8dad0edf34ae64096 100644 (file)
@@ -1,4 +1,5 @@
 /include/ "kirkwood.dtsi"
+/include/ "kirkwood-6281.dtsi"
 
 / {
        model = "D-Link DNS NASes (kirkwood-based)";
                                      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>;
 
                nand@3000000 {
                        status = "okay";
+                       chip-delay = <35>;
 
                        partition@0 {
                                label = "u-boot";
                        };
                };
        };
+
+       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>;
+               };
+       };
 };
index 08a582414b88272f04e94207b0ad3463bb4fbff6..2e3dd34e21a554298a029dc1bdf563c26f19ea59 100644 (file)
@@ -1,6 +1,7 @@
 /dts-v1/;
 
 /include/ "kirkwood.dtsi"
+/include/ "kirkwood-6281.dtsi"
 
 / {
        model = "Seagate FreeAgent Dockstar";
        };
 
        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";
                        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>;
+               };
+       };
 };
index 26e281fbf6bc36383d2c505e6991686a2e7eea4d..f2d386c95b070ba097f6ec7e716a5c9c441a6938 100644 (file)
@@ -1,6 +1,7 @@
 /dts-v1/;
 
 /include/ "kirkwood.dtsi"
+/include/ "kirkwood-6281.dtsi"
 
 / {
        model = "Globalscale Technologies Dreamplug";
        };
 
        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";
index 7c8238fbb6f96ab5027561a942339d2078915211..1b133e0c566e80b4c4e47ab1cd2531772065489d 100644 (file)
@@ -1,6 +1,7 @@
 /dts-v1/;
 
 /include/ "kirkwood.dtsi"
+/include/ "kirkwood-6281.dtsi"
 
 / {
        model = "Seagate GoFlex Net";
        };
 
        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";
                        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>;
+               };
+       };
 };
index 66794ed75ff1d3162dc8a567b7f36b37c020b1f2..71902da33d6383583659adf35b16d7b3a1684c85 100644 (file)
@@ -1,6 +1,7 @@
 /dts-v1/;
 
 /include/ "kirkwood.dtsi"
+/include/ "kirkwood-6281.dtsi"
 
 / {
        model = "RaidSonic ICY BOX IB-NAS62x0 (Rev B)";
        };
 
        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";
                        gpios = <&gpio0 27 0>;
                };
        };
+       gpio_poweroff {
+               compatible = "gpio-poweroff";
+               gpios = <&gpio0 24 0>;
+       };
+
+
 };
index d97cd9d4753e298689f3e9331eb7945569b416cd..504f16be8b54bf682a4c45413a354a48fd27c35e 100644 (file)
@@ -1,6 +1,7 @@
 /dts-v1/;
 
 /include/ "kirkwood.dtsi"
+/include/ "kirkwood-6281.dtsi"
 
 / {
        model = "Iomega Iconnect";
        };
 
        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";
 
index 865aeec40a268da8f2a0b2ab3416ccbad4da90f5..6cae4599c4b3e620974dbfa318119db952a56136 100644 (file)
@@ -1,6 +1,7 @@
 /dts-v1/;
 
 /include/ "kirkwood.dtsi"
+/include/ "kirkwood-6281.dtsi"
 
 / {
        model = "Iomega StorCenter ix2-200";
        };
 
        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";
 
index 75bdb93fed26a9b4d2843d4a230a5389d2f0af46..8db3123ac80f49d0bef30aa4c6c79dcf68690a51 100644 (file)
@@ -1,6 +1,7 @@
 /dts-v1/;
 
 /include/ "kirkwood.dtsi"
+/include/ "kirkwood-98dx4122.dtsi"
 
 / {
        model = "Keymile Kirkwood Reference Design";
        };
 
        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";
index 798e60eeedf3bb0abbf0acfd2c5d997c364fe0d2..37d45c4f88fbf3bd5db139c43b0f7588aeb70d09 100644 (file)
@@ -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>;
                                      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>;
+               };
+       };
 };
index ac3c080bed2129942bc5f9b4cf10e77d1fac9c98..262c654037605cee7c32310b28d481b5fab3d1cf 100644 (file)
@@ -1,6 +1,7 @@
 /dts-v1/;
 
 /include/ "kirkwood.dtsi"
+/include/ "kirkwood-6281.dtsi"
 
 / {
        model = "MPL CEC4";
         };
 
        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";
 
index 9a2606c8b78fd21a63d0b03db6976c02044d9e87..49d3d74d4d3827534e08830e3d1a84d2b4bf12d3 100644 (file)
@@ -1,6 +1,7 @@
 /dts-v1/;
 
 /include/ "kirkwood.dtsi"
+/include/ "kirkwood-6282.dtsi"
 
 / {
        model = "Plat'Home OpenBlocksA6";
                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>;
+               };
+        };
 };
index ccbf32757800ebc7480f776698e8a14213827ef8..8295c833887ff6851322f52abac570b25ab9aa08 100644 (file)
@@ -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>;
index fbe9932161a125a3f50d8361786ac9993acb8a64..df3f95dfba3341d07628a3ce212d63cc27f0f3ba 100644 (file)
@@ -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>;
index 4e5b8154a5be5d95535cd5eb9d66f894670c0946..a990c30f0a2602936f76c3cd79cca99e2966ad40 100644 (file)
@@ -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>;
                };
 
                        status = "okay";
                };
 
+               ehci@50000 {
+                       compatible = "marvell,orion-ehci";
+                       reg = <0x50000 0x1000>;
+                       interrupts = <19>;
+                       status = "okay";
+               };
+
                sata@80000 {
                        compatible = "marvell,orion-sata";
                        reg = <0x80000 0x5000>;
index e5ffe960dbf3e43181d28e7519b35911c3f95f2c..1582f484a86762976bc6f40d27429d0644a00672 100644 (file)
                                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>;
index c6f85f0bc53100e27362efaa5174fbc8e314d843..27f31a5fa4947aa530d74cfa4c0260fc406ace7e 100644 (file)
@@ -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>;
                };
 
                // 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>;
 
                };
 
                // On-board eMMC
-               sdi@80114000 {
+               sdi4_per2@80114000 {
                        arm,primecell-periphid = <0x10480180>;
                        max-frequency = <50000000>;
                        bus-width = <8>;
                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 (file)
index 0000000..39446a2
--- /dev/null
@@ -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;
+                       };
+               };
+       };
+};
index 74b8a47adf91561494e0d7d884d8aed0c6cfc785..43eb72af894823d294cbf3ca951b9a3e498088c2 100644 (file)
                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>;
                };
        };
 
-       i2c@7000c400 {
+       hdmi_ddc: i2c@7000c400 {
                status = "okay";
-               clock-frequency = <400000>;
+               clock-frequency = <100000>;
        };
 
        i2c@7000c500 {
                                        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>;
                                };
                        };
                };
+
+               temperature-sensor@4c {
+                       compatible = "adi,adt7461";
+                       reg = <0x4c>;
+               };
        };
 
        pmc {
index 331a3ef24d591d0f84d04fce3d92d82d40742955..289480026fbfadd52308a49f3134b43edb2e04db 100644 (file)
@@ -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";
index e58a0e60f711d99af9dede6b5947243f1e2fd7be..420459825b46d680f076fde49a307209eaf8780d 100644 (file)
                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 */
index 5b3d8b157b336eafd58511500e87a4d9076828af..a239ccdfaa526ac06b0b249212b0b8a5e23c802e 100644 (file)
@@ -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>;
                                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 {
                                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 {
                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";
                                        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>;
                                };
                        };
                };
+
+               temperature-sensor@4c {
+                       compatible = "onnn,nct1008";
+                       reg = <0x4c>;
+               };
        };
 
        pmc {
index 9aff31b0fe4a5c156b38c8d6a6b38ea172ca8081..402b21004bef5859908d00d4191878a44ff44260 100644 (file)
@@ -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>;
index 27fb8a67ea42ffa3887f646a903bbb9f04be3493..b70b4cb754c8bd1e60b6d7768e3de0eb83d6186a 100644 (file)
                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>;
                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 {
                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>;
index 86854f1abd586cdee975a57081384a62d99518e9..adc47547eaaee94115cb9991bcc5782c7cdffefe 100644 (file)
                                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 {
                                        "lspi", "lvp1", "lvs";
                                nvidia,function = "displaya";
                        };
+                       owc {
+                               nvidia,pins = "owc", "spdi", "spdo", "uac";
+                               nvidia,function = "rsvd2";
+                       };
                        pmc {
                                nvidia,pins = "pmc";
                                nvidia,function = "pwr_on";
                                        "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";
+                       };
                };
        };
 
                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>;
                                };
                        };
                };
+
+               temperature-sensor@4c {
+                       compatible = "onnn,nct1008";
+                       reg = <0x4c>;
+               };
        };
 
        pmc {
                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 */
index 94a71c91beb580b2f88f080cbbeeeeefa5bc0ba2..20d576ecd5555d61c1f66057fb105c980ff44d8d 100644 (file)
                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>;
                clock-frequency = <216000000>;
        };
 
+       hdmi_ddc: i2c@7000c400 {
+               status = "okay";
+               clock-frequency = <100000>;
+       };
+
        i2c@7000d000 {
                status = "okay";
                clock-frequency = <100000>;
                                        regulator-always-on;
                                };
 
-                               ldo6 {
+                               hdmi_pll_reg: ldo6 {
                                        regulator-name = "nvvdd_ldo6,avdd_hdmi_pll";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
                                        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>;
index f40cfbaa7c7e3a70438570dd2dde4626191dafad..b8effa1cbda7331078d9d85bcc3d7a9bf9a891d3 100644 (file)
@@ -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>;
                #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>;
                #pwm-cells = <2>;
        };
 
+       rtc {
+               compatible = "nvidia,tegra20-rtc";
+               reg = <0x7000e000 0x100>;
+               interrupts = <0 2 0x04>;
+       };
+
        i2c@7000c000 {
                compatible = "nvidia,tegra20-i2c";
                reg = <0x7000c000 0x100>;
                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>;
                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>;
index dd4222f00eca9b4dc82637976283235906d1b708..adc88aa50eb634e5c36b002f6a06420aa6917a7c 100644 (file)
                        gpio = <&gpio 83 0>; /* GPIO PK3 */
                };
        };
+
+       sdhci@78000400 {
+               status = "okay";
+               power-gpios = <&gpio 28 0>; /* gpio PD4 */
+               bus-width = <4>;
+       };
 };
 
index 0828f097ca860490b7edd786b619bf889535014a..08163e145d57d10691f85ae6de770321d5f168f4 100644 (file)
                        gpio = <&gpio 232 0>; /* GPIO PDD0 */
                };
        };
+
+       sdhci@78000400 {
+               status = "okay";
+               power-gpios = <&gpio 27 0>; /* gpio PD3 */
+               bus-width = <4>;
+       };
 };
index b1271a894327912f0a4d15f3b6fb189865dad6ea..bdb2a660f37643deb8ea6501d51e14b8754fd608 100644 (file)
                                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";
                                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>;
+                       };
                };
        };
 
                };
        };
 
+       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";
                        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>;
index fed8dca1692df79f1314b5f4f4e78b30da960860..529fdb82dfdb9683405a02c86e42e0850590f633 100644 (file)
@@ -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>;
                #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>;
                #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>;
                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 (file)
index 0000000..95892ec
--- /dev/null
@@ -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 (file)
index 0000000..401c126
--- /dev/null
@@ -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 (file)
index 574bc04..0000000
+++ /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 (file)
index 0000000..c772942
--- /dev/null
@@ -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";
+};
index 5b8215f424c5a72e283fb979b5d4828f1d386738..728a43c446f8a5e2acd25f66ae03c2bd867fa0fb 100644 (file)
@@ -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
index 048aaca60814c99d2143edee134d128ba9264a08..7bf535104e268dafb0bfb7671e2b428266103e29 100644 (file)
@@ -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
index 62303043db9cf5913938e74c6ec5c6c66bd0d62d..a1dc5c071e71250879e27ae3c92632a3409375cb 100644 (file)
@@ -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
index 250625d5223fe88ff9e505b97a1c3fbb01d03215..231dca604737e1564913c48edda18176f9aa00f8 100644 (file)
@@ -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
index 0b65d792f6640433a2bc51c3fed50525c899ef63..0c4e17d4d359a42cb372341045068f7dc44462c6 100644 (file)
  * 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)
 #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 (file)
index 0000000..883d7c2
--- /dev/null
@@ -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
similarity index 61%
rename from arch/arm/mach-zynq/include/mach/debug-macro.S
rename to arch/arm/include/debug/zynq.S
index 3ab0be1f61914e04bd60d520f821fcda1abf6da0..f9aa9740a73f09676d5a963f47e2d8e4f7d83e6c 100644 (file)
@@ -1,5 +1,4 @@
-/* arch/arm/mach-zynq/include/mach/debug-macro.S
- *
+/*
  * Debugging macro include header
  *
  *  Copyright (C) 2011 Xilinx
  * 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
index 1862d8f2fd44c00d1d535a1b447a5ab6cdf333b7..0cd63d080c7bf2d93f35db5a69e3debc5147351e 100644 (file)
@@ -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
 
index e34c1bdb804db921ecf92528b8721131d54c1449..958358c91afdc8a6f2c17ae7bead613db4cea5b3 100644 (file)
@@ -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.
index 8ce068240c69284a30ee54c8de879b0c38572ff6..7aeb473ee539b42a3b0bfc028bdd111cabd0c14c 100644 (file)
@@ -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),
index 2a1f8e67683d90c6916b9c3657f7975b9760775c..3ebc9792560cebed75a53883e42e774742c5660c 100644 (file)
@@ -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,
index c65e7b8d7a8115c66d830761fe138a7e91c70969..b67cd5374117b4405e0f153d77cd4040bb3f83c5 100644 (file)
@@ -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 */
index 1f6fac21b2c88fb95c187df78402f5dbf5b99931..eda8d1679d404ef3a75ad999fabd333c23296b58 100644 (file)
@@ -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,
index 9d3e9b8b9926bfd7b5a259f9d36e96e67a927261..2998a08afc2d91a020700807ff9fcd0ca813b68c 100644 (file)
@@ -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),
index 6ce6d27e2442d453213a0952180368ea62d95c81..92e0f861084aad210fab02837401eb5185255c98 100644 (file)
@@ -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,
index 82deb4d748b26a135834151dc8bb411191b44f63..b9fc60d1b33a2f2e6f0e4feef4f44fb82dda38e9 100644 (file)
@@ -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),
index fb98163b9b3adc6750520295b14c9a83137895bc..ed666f5cb01d577ffb219f2a7857ba84e913e619 100644 (file)
@@ -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,
index 45d753d473f68b086cb828873d20990a03fe2635..d3addee43d8dac22689c5e3b3970564dbc0d2aca 100644 (file)
@@ -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),
index e35964201a10b877f1e05fbabf4af782d0cbd4a3..827c9f2a70fb9a3f36c40570694bd2ed6960e652 100644 (file)
@@ -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,
index 44e3a633fda7d071c0a22a158523adf5c9613788..eb98704db2d92a4b24835b226cedcf7814260529 100644 (file)
@@ -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),
index 160384d93db204a6ff3d7fb468a15e37f254e04a..ddf223ff35c41ba21999cc1a829975843bab51f3 100644 (file)
@@ -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,
index dfb2c0c13fb560331fc3179e3272cb909a77eecd..44a9a62dcc139f1b096d44b5e1c158cea168b3f2 100644 (file)
@@ -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),
index 78e025074423244456cb58cf4baa4d4c8fba0fdd..48a531e05be3995cd6fce2a31535e8d1d473ed46 100644 (file)
@@ -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 = {
index 7b512380236884722faca87b0a9a07789a5f7b58..1b7dd9f688d36b14f772725dbc7c6c079c4d64f9 100644 (file)
@@ -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 (file)
index b8260cd..0000000
+++ /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
index 5c5a95a9d7d2b17c716ebc06e96ea31c529046c8..04a6c4e67b146dee4aeaab855b55a63f554e3674 100644 (file)
@@ -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
index d4f4dbfc0e59bf97682e950012828efb966a22c7..7211772edd9dee20e51501750b66f33448cabbd1 100644 (file)
@@ -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);
index 070c7b6d3d86c18b164074fe89bcc55d9fb83d89..91d5b6f1d5afa80c6c0fbb5d35a88af1a2750838 100644 (file)
@@ -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
index 66135eedf491302e5fa23580cdd6d7d78da89320..b189881657ec0dbe0fe96c7de2dbcce946ae6284 100644 (file)
@@ -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
index fa8a13405c94388de84e9b9d5de36d47f6cfbf5e..efead60b943699d160fa8754e9435cfba4a658fc 100644 (file)
@@ -575,6 +575,10 @@ static struct clk exynos4_init_clocks_off[] = {
                .name           = "adc",
                .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,
index 4478757b930126bc112062a9956ab5c43124e97d..7652f5d78a56664dba722ec0dea19e51d0dd3937 100644 (file)
@@ -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 = {
@@ -615,6 +620,11 @@ static struct clk exynos5_init_clocks_off[] = {
                .parent         = &exynos5_clk_aclk_66.clk,
                .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,
@@ -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),
        }, {
index e05f6cca2c9b77a5c49679861219b1200cefc518..ddd4b72c6f9a9530e432399708b7e38af889e1c6 100644 (file)
@@ -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);
index cff0595d0d352c0d69cb9023b9b1cbf555fd16c4..8e4ec21ef2cf6ba3790b222e3e1ced6684ee2387 100644 (file)
@@ -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 (file)
index 17c9c6e..0000000
+++ /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),
-       }
-};
index f4d7dd20cdacdb31c2f99ea7b9c05b62e5b0a8ee..c3f825b279473447ebbb06fb0fc4c2ab168b6987 100644 (file)
 #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);
 
        /*
index e0f0ae3e0cf9165aad26708789319de69fafc8c6..1f4dc35cd4b9b88479e4b16496a7f62a05c58a46 100644 (file)
 #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)
index 61b74e12d12b1cef2d9a2a39de08ef2cd9ba026e..1df6abbf53b8cb4364884f4ee5c7018b83968bac 100644 (file)
@@ -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
index 3f37a5e8a1f450d4d4e6797d0570c51df5b2805c..b938f9fc1dd1288d781241366daaa90d65582907 100644 (file)
@@ -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,
 };
index 6df99c06419d1c798dc270ad837658af7dc6dcc3..92757ff817ae1de50c9405b70b339739265ef14e 100644 (file)
@@ -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
 };
 
index f1326be80b91700b9fa9669d36e3729af0db0f4c..929de766d4906cdb8856da45baf47301528fb3ae 100644 (file)
@@ -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
index 69359a0c8a1c8f643030b8fbc210d59629e9dfc5..27d4ed8b116e7972ca7c2539ddf1ef8a3896afe2 100644 (file)
@@ -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)
index c606080b5dfa0d32d5044e204f3cf8f318636707..e6f4191cd14c1af36c5df0ac14bb9d136f2f22e9 100644 (file)
@@ -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,
index ddb92631252d0511625214a056f1dd00dddcf5fc..a1555a73c7afd08f46cec725159b8b3ce1d2afd8 100644 (file)
@@ -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,
 };
 
index 8dd6a1e8030dd85963a9b3ae84f7ce584c4bfbbc..b7384241fb03ac836e08a74bab3cac4aae8c8881 100644 (file)
@@ -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,
index 2d6bc83d5c99c3ccd0e5ef96dde42e8180f7cd9f..9e3340f1895069803f86ab383a23307b6ab97dac 100644 (file)
@@ -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,
index c06c992943a139bc3017854b19c4eba1cb09d4c5..8df6ec547f78fcaa4234c8a08c0fe4a32187414f 100644 (file)
@@ -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;
 }
 
index c0bc83a7663ee5877edfc0ff768b63a1ed1a2e30..9f1351de52f7533a731f6d2d2d26bb644c639c09 100644 (file)
@@ -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
index 4e24b8c77eb438c5806b185427a5932456528709..1ad0d76de8c7b57029faccb9c88dda430a93bab7 100644 (file)
@@ -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.
index fe47b71469c91863eeeb74dd7179f38fc4d5c264..0634b3152c24ca6918ba6584c8da914fd5d7dacf 100644 (file)
@@ -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
index bc885801cd68767aec757a851a8997f3ba5bbc5e..b197aa73dc4b448ad603256f8ea1ea5a9be8e30c 100644 (file)
@@ -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;
 }
index 448476958e7fc8347258a3d361659b487077e03b..7f2c10c7413abaf0786b45a29933bc60745bd12c 100644 (file)
@@ -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,
index ef8db6b348419e9c6d75a9b9ca837e854803c132..7191ab4434e52b5c881e170e9e7925e918ba42f5 100644 (file)
@@ -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 (file)
index 0000000..e17dfbc
--- /dev/null
@@ -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
index 5f1510363ee76f469358be2c86a664eed70f9308..2fdc9bf2fb5e812c177e14d805fc71562a060065 100644 (file)
 
 #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
 };
index 978b6dd00de401e7662e0fc1e7d1aa003df57e20..4eb1b3ac794ceb38ee928a3a67654a0192cd8492 100644 (file)
 #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 = {
index f7e7dbac8f4be64464d70aca1d621d7bef52c682..19d3f54db5afa0cd2669f775dbf868ec98da2681 100644 (file)
@@ -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__ */
index d018ad4bcc3cb0728ce2be3ae01a8802b7dc1189..503d7dd944ffcbacf0548c4ef093eae1d688a8ba 100644 (file)
@@ -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
index 43d16d6714b82bed34aeff6ffa9240032b5560a2..a1aa87f09180f91215a3d2c95c3c6153f82f87f2 100644 (file)
 #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);
 }
index 6912882b0aa9710e598840fb850186170f3293a1..d7196db339841fa49f517b3c14602278de15a57f 100644 (file)
 #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);
 }
index 8a8ebe09e512589d3f1c9f2a8483af476972487b..08248e24ffcdba8179413c15dd25b60a55b40d96 100644 (file)
@@ -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);
index 5dcd0d62aa42ba23ec8a9d731ed76d695b77db6b..9db979aec82e6e112d40be72b0b08b04ad386096 100644 (file)
 #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);
 }
index 6d3a56421142e4c0700046d710335caec3ebdf56..9f6f496380d83c8c2b3a46b1e4b2d7063183c0af 100644 (file)
 #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");
 }
index 24f5aa7f698bb182c708107013a16a2c1e73e10a..c8ebde4919e26fa4bf1db5eb5e8556e2d63ddda9 100644 (file)
 #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);
 }
 
index e4ed62c28f54dd07b3de1da6aea99987454e071a..f655b2637b0e2b4822efc185c499095c44bc6b9e 100644 (file)
@@ -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);
 }
index f7d32834b757fda283de6db627d4fd4a4bf68491..44e4605ba0bfbcb70b1ef1827acdeeffc03cbcd1 100644 (file)
 #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
@@ -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);
 }
index 7e18cad9b796dd15ff90b91196bb94900df5e523..4ec8b7ae784a298af778cd191b25b671d810c39c 100644 (file)
@@ -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);
 
index e78a227468e64a6cd4cbef29463055f633c02416..56bfe5a1605ac0ce9d3bda04055e2636e88aae5c 100644 (file)
@@ -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);
index 78596c4f76d243fd1766f4b7edb641ba8a4bc01e..8821720ab5a481ca048b0acb1ef01010055ffa7f 100644 (file)
@@ -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);
index 027ce83f3fe51217c6841f27b375765e266078f3..f58d2e1a40422e06346387350298ee08f233bb0c 100644 (file)
@@ -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));
index e807e8cfdd44a346ab5183a55813b93daa64ecab..815fc6451d526bdf3db94fa082879c1711093e36 100644 (file)
@@ -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);
 }
index f3bfedae3a20f58358b6d3558221fc3c833b2a2f..acb0187c7ee1d036d4c119574e46fab6dbbef48d 100644 (file)
 #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;
 }
index e2ec9d891fe3eec469f32ce9b23c46ddc0ec89f6..15e69fcde9f4d262f80d749938ce8c477130e0d9 100644 (file)
@@ -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);
 }
index 4748ec551a6818f6f2eb55f520729c3ba17cc48e..98070370d602de66f781c8187ebdaf0bc8015e38 100644 (file)
@@ -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);
index 7c3792613392ddc7a4936a5f44388c5a23c4dd58..856f4c7960618dad52fac637bf17ad21792b6acd 100644 (file)
@@ -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;
 }
index e4cfb7e5361d2fa25978502fbab1ac296208d61e..f1c972d87bacc164b297b6e7f8088818a09aa168 100644 (file)
@@ -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;
                }
index c744946ef0222e89623a038473497ad007f7b5ef..706dc5727bbe86ea110517cb0f3fb8e470ab6d3c 100644 (file)
@@ -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
index 22ef8a1abe0835cc7d0143c9456b984794c10113..5ccdf53c5a9dcd0c3a6814d61b49d083e34a89eb 100644 (file)
 #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 = {
index a118e615f8650a81b100348abbbae3bc30b7c0ea..b549d0571548ed8d3682e6946e2bce6f0e2fb4ed 100644 (file)
@@ -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
index 4953cf7a51232ef1de9cd7ac30e2a629686b626c..2274bd677efc4a688cf25025f3484a813a0bb68c 100644 (file)
@@ -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>
index 563ba167bb161b04f35d3769ebe74a0347495189..1051935f0aac01280f3dfa55646b77ffed5911af 100644 (file)
@@ -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>
index 584b6fab894bb4c5978a30fb2045ec339de0e623..c33dceb466078630108f56f29ac0e621a745b7e1 100644 (file)
@@ -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>
 
index fbc986bfe69e1770e5201145febcc4e171778c24..2948b0ee4be872bf9f438b372f5afec322e1027e 100644 (file)
@@ -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>
index 60d917a9376326e26a385ccc542213c2e94f0ca9..7a05895c0be398520a1aec8d8beacb6830ada28c 100644 (file)
@@ -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>
index 1ebc7e08d6e5b9cad9ce1386007c387d4fb0963f..20ed52ae171400fa1d6a3d1eb963f159c172a03a 100644 (file)
@@ -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>
index 978aed85d3283f5983430b6accca96c5d614c637..e190611e4b46654545c9f647dc014e97f201b056 100644 (file)
@@ -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>
index 5a3b80617a11e13ab32839a8f1766ed5b3ba96bf..499b8accb83d10f46a289f437c6dcc9795e2f825 100644 (file)
@@ -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"
index 7ed8c1857d5650856a477e46101127065a4f05f1..77924be37d4181fe777940b9d5a214f9e7be59b6 100644 (file)
@@ -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>
index c6d8fdf92e9ca8fff8548cf1d5740a3220768bcb..b0d4723c9a90718ccbef119dfdf95412b33c4109 100644 (file)
@@ -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>
index 66d663a6ef3a3b1eadfa1a34735fcecf4e872ee4..7a7690ab6cb8a8e76c279b4955fe5ada77586801 100644 (file)
@@ -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>
index 2265e5826883da639bc6da0416b37264816845c0..be0f62bf903793e3856dc2ae81bab4c83be40199 100644 (file)
@@ -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
index b455ffc12ebe180f1385c53055e8c28ac14fd00c..a8004f33b7e2ac6357bc8454e95d9a69dddcfbe4 100644 (file)
@@ -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
 
index 6601754f95128b65eaaa6b66141d598f24d6db9c..7b201546834d271ce309803144a57339622a7c81 100644 (file)
@@ -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>
 
index b626dbe6f7bc0f891d74734cd4d7bbecc6f82edc..9a3878ec22561dea38ba584521e66f6355bd2cf4 100644 (file)
@@ -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>
index 07005fe40a2a65eecc529ea9d06fee342ff26150..60529e0b3d67aea6a98da9c6774d81c4ca539e28 100644 (file)
@@ -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"
index b67fe11d0d9492c004f560677019eef190aa20a8..f1d6efe079ca27476a21302faa09049d20e7430e 100644 (file)
@@ -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 (file)
index 0000000..7e5febe
--- /dev/null
@@ -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 (file)
index 0000000..eda079b
--- /dev/null
@@ -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 (file)
index 0000000..ea64ad6
--- /dev/null
@@ -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 (file)
index 0000000..bdf3948
--- /dev/null
@@ -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 (file)
index 0000000..aa56c3e
--- /dev/null
@@ -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;
+}
index 8c5b13e7ee61eaa8ab92a17c1ff3862de11ae2c3..25b1feed480d8ae9089d63da213377dfd5d6dc5d 100644 (file)
 
 /* 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)
index 399534c7843b353800de1740239d8dceecb87033..82572e277b970b64ab32ff4130def01a91242905 100644 (file)
@@ -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,
 };
-
index 825e44cdf1cf80cb76fe25865a59f109d2b0e66f..d8620105c42a3a0681c59de527b3f5d9c8e41b96 100644 (file)
@@ -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);
 }
index e1777371bb5e9813c4c41baf664eb2eb3e3170c2..19f54d433490cb4e6079427d2fa52364e67aa215 100644 (file)
@@ -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();
 }
-
index 46683b3c2461be67fecb1422a7ae4da82ca954de..f467d072cd026da1a39b811b282da276f42c9716 100644 (file)
@@ -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();
 }
-
-
index 1c2041fbd71820ad8de6fa1bd66cc1a20bb68e2d..ae2b35e76dc8e1e7592b1fd84d969d6f033e603a 100644 (file)
@@ -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;
index 6cf298e262f61fdabdc85fd40f2e7bea00442abe..eb69acf21014e023184baac01b8821c528b7ed56 100644 (file)
  * 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;
 }
 
index 53646facda45fe246df6b6eb264e896a527441fa..0ec9f6fdf0463bb6ff435f250c748db075c62ca4 100644 (file)
@@ -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>
 
  * 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,71 +73,13 @@ 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;
        }
 
        return clks;
 }
 
-/**
- * _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
@@ -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;
 }
index 8463cc3562450155ee1a5b6eee6f506ba9366d89..924c230f89484473f057246fb7f3a8b53a28c2bd 100644 (file)
@@ -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);
 
index fe774a09dd0cf32dd11ab99a952943b9a1523cb9..f10eb03ce3e27493ee1d52b18444ff52d4cf1507 100644 (file)
@@ -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,
-};
 
index e381d991092c83385964b9b75010eddc5107896f..e4ec3a69ee2e749b1d40b80065956f23b4424070 100644 (file)
@@ -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) */
-
index ff9789bc0fd1a1697fb2bac2d0b7574f75ae5a26..9917f793c3b6979d125f3b9bc690bf0814dadeb3 100644 (file)
@@ -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 (file)
index 608874b..0000000
+++ /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;
-}
-
index e37df538bcd3235e5737b3e93e74c98bdeacfb71..cef0c8d1de5274e4eecc24dae4aff9bfb2c02cbb 100644 (file)
@@ -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 (file)
index b179b6e..0000000
+++ /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;
-}
-
index 5f7faeb4c19b4ce995c595085f3d5d81ac1ccc02..1ff646908627df9a2b161f404b778b2ab8d6f334 100644 (file)
@@ -28,6 +28,7 @@
 #include "cm.h"
 #include "cm-regbits-24xx.h"
 
+struct clk_hw *dclk_hw;
 /*
  * Omap24xx specific clock functions
  */
index ce809c913b6f29f7cc65741af5e0508f1f40a49d..539dc08afbbaf3cb93536f600a5bb930b35d7d55 100644 (file)
@@ -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 (file)
index 17e3de5..0000000
+++ /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;
-}
index e41819ba748239d593ab5305e13334130532aa1a..4596468e50ab13cba0f3890a7ce1c2b02c063a8b 100644 (file)
@@ -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,
 };
index 622ea05026107dd4332341791c9f8c3a4ede5ee7..4d79ae2c024188b3e5e42a7fde8fd0f925e27a89 100644 (file)
@@ -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,
 };
-
-
index 0e1e9e4e2fa43e7b51fb921f6d5f222999f75f36..8f3bf4e509082fad0dcb412a0a21573b68e4a485 100644 (file)
  * (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,
-};
index a7dee5bc6364f83881fa49e212e8b952d20aab78..945bb7f083e96f71ccf88320faffbcb3cc642576 100644 (file)
@@ -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
index 3e8aca2b1b61d71ec0da6382960088867ce5e0e9..4eacab8f1176b7437022bfa78b31adfdce8345a7 100644 (file)
@@ -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)
index 8bbeeaf399e219b6f9d000ee2aa7add260ceca13..8cd4b0a882aec39418c8adcd4e41daab0a010c0d 100644 (file)
@@ -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 (file)
index 6cca199..0000000
+++ /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 (file)
index 2a450c9..0000000
+++ /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;
-}
index b9f3ba68148c793d368f51174ca164c4a1081c4f..ef4d21bfb96478da0b9ef681c931303aa9fb1bf4 100644 (file)
@@ -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,
 };
index 64e50465a4b58dddbaa36af027ac775de211c978..384873580b2395321a921463795d63a966cb3eee 100644 (file)
@@ -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;
 }
 
index 11eaf16880c4386dc1a9faf52e99c26984f8d97e..669ef51b17a8e12cd73b09f9e9724dda4c09d71c 100644 (file)
@@ -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
 #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
 #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
index 59598ffd878333978b1ca2ed52a26fee3b0e7f72..adf78d325804f865627babff0742b36e07618533 100644 (file)
@@ -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
 /* 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
 /* 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
 /* 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
 #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
 #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)
 
 /* 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)
 
 /* 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
 /* 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)
 
 /* 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 */
 
 /* 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 */
 
 /* 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
index 98e6b3c9cd9b8610fcf85656b5ea4ac46f64493f..bfbd16fe915110e219dadb776832a0b1779f9834 100644 (file)
@@ -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
index 4ca8747b3cc92b101a433199bf123e227a976bad..3d944d3263d2ae36966ed9f0a01e0c5849288948 100644 (file)
 #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)
index 3cff7dc514df3201bb75f5bb7a583905439d3f79..c67a731cfbb708f9e36d5d8f843d3ffb6119fb31 100644 (file)
@@ -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"
index e5aba58da5d2f70343296cdedd7bb34e8099118b..612b9824987351db13d331a7a0c302c091bf4b91 100644 (file)
@@ -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"
index eacf51f2bc27ba766f05571e34ba14da2ce1fb75..fafb28c0dcbc46274232f7225fef46d74233eed5 100644 (file)
@@ -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,
 };
index 5854da168a9c4e74602893077d68a29c36c56ab5..d3326c474fdc4b2847bc5c2834838cce39002768 100644 (file)
@@ -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;
 
index 8607735b3ab3c96b8a6fecf25066843a47aaee57..db969a5c4998d3c9b1904ff90d2134e2eb3c991a 100644 (file)
@@ -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)
index d102183ed9a5b21289b61678b9f4b49746d68c31..94a349e4dc966196d763a51f5f719c2fc071a7de 100644 (file)
@@ -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 |
index 6eed907d594cc700134ad0e7716df079d1b793c8..11d0b756f09897be435075302392131a35aa686b 100644 (file)
@@ -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);
 }
 
index bf6117c32f4bc0302522d0ea6f54b83d7c171ea3..65468f6d7f0e62382ee6df3c16fcb2cad5eb054e 100644 (file)
 #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;
index 79f4dfc2adb3cec5d6f40af94796bc8558492a99..fe0a844d5007a7775cadf78e357b541bbb80b153 100644 (file)
 #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);
 
index 9df757644ccefe6f73ebf547dfa0f5782af26790..2c3fdd65387b56c542d6d97cbc093fcf69a51b9a 100644 (file)
@@ -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
 
index bf496510eb5e31e2acd4cdb6afbb5a5c46059946..df49f2a4946122533715b71b6a8c81a080b34b8c 100644 (file)
@@ -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"
 
index 0ef934fec364a674d98e09cb625425e8461e4bcb..e065daa537c07bd8c8946d394d9ab60c0b120c3b 100644 (file)
@@ -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);
index b3b00f43dd7ca43d9a7fdbb8ffae75e8cde47944..4653efb87a2721ea20a9fe06a30a6c204d6d2282 100644 (file)
 #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;
@@ -1991,6 +2016,42 @@ static void _reconfigure_io_chain(void)
        spin_unlock_irqrestore(&io_chain_lock, flags);
 }
 
+/**
+ * _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;
index 87a3c5b7aa74dc42ce7968579a871314a8d7fe20..3ae852a522f95fd0a8ad5dc53a6dbcadb5a4faa7 100644 (file)
@@ -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,
index e8efe3d1da6c786639eef9e924b26d3e09096fdf..b5efe58c0be09cb4953dfcb70e0e93f21524a721 100644 (file)
@@ -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"
index 32d17e3fd72747e62f509d5888c1d8a2cb9eef19..6c8fa70ddaddad333545bb10a9e5d5bfe4204950 100644 (file)
@@ -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"
index 40d6c93d98530cd673b3ba1ff29245a94a79b3da..534974e08add21655fbea5fe647c45670c2e0102 100644 (file)
@@ -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"
index 0db8f450bad973aa9fdd6e67e3aaf543717283cc..e596117004d48c8faccd1c6c3b792b0b623d7b89 100644 (file)
@@ -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>
 
index ad8d43b33273917edd49b6e228fe06f978abdc41..32820d89f5b41f917ab270273a5a0a0df7266c5d 100644 (file)
@@ -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           = {
@@ -684,6 +685,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
  */
@@ -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,
 };
 
index 7f73f2132acce82eb103203814af4378f90f231b..ec4499e5a4c931f0869fc7bee317d4d171a7739e 100644 (file)
@@ -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>
index 26f8e9f18190ad991e72702abd0f16922c5934f5..eb61cfd9452b57e3d6ffaf98ba02c795a533aebb 100644 (file)
 #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>
index 7e437bf6024ca2ef694913c3a3eac9dac1f16e87..336fdfcf88bbb51004098ad846dec505e9da4d40 100644 (file)
@@ -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 */
index 4d76a3ca5bf3de373b08104bc1792e013671e835..e237602e10ea45ee3fe0f932242df79cd038bf11 100644 (file)
 #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;
index 2bf35dc091be445ac8cc8ef3f833a261c76a96bb..fefd40166624d97196c8f000c63061f01c18761f 100644 (file)
 #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
 #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
index a9fd6d5fe79ef0dcb8484117e3e1c47cd324a04d..d470b728e72085b7bcfad5d24fdd9c0a0919cc97 100644 (file)
@@ -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);
index 331478f9b86403cd73d770bc564602c6b912b01e..f4b3143a8b1d23f104419181c0d266b07e31ad78 100644 (file)
@@ -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;
index fc3c96d5e013fc55b6ed40b21b404f379b90ef19..c22503b17abdcea08d58126c0eefd714e0fec841 100644 (file)
@@ -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
index 13e1f4303989aeca16241e79637e62f9c429d497..c333fa6dffa8193ec8f7b8dd8290609c8ac53c92 100644 (file)
@@ -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;
index 7703200614222aa8e16aaf15f715191dee62a71c..7be3622cfc850711bea6f5b1385b7631ea7033dd 100644 (file)
@@ -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"
index 7da75aed1514bf8374aa54310b70c29a7d895693..aa6fd98f606e30aa96c164b2ce3dd40719777e0c 100644 (file)
@@ -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;
index 638da6dd41c318d8038caecff47627770dbf6c08..91aa5106d637dad8d8ab130906d1e82d8ba92e18 100644 (file)
 #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)
 
index 838b594d4e13f546ac45d32fa84218216fea76ca..b0a2142eeb9145680576722012d877aac0e4f1a2 100644 (file)
 /* 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)
index a1a266ce90dac1e2e0874128f2ea260b3b979dff..ac25ae6667cf92c448d37a9fc25058d69f26be19 100644 (file)
@@ -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
 
index bf24fc47603b89b936113964cefedc43f393f13d..faeab18696dfff6dc8e092c90c25fdd40be6f9a6 100644 (file)
@@ -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)
 {
index fe8a14f190abc001ba49eb46e7f57c13994e042e..3194dd87e0e4278accfd0536175fdfe8b4cb2e99 100644 (file)
@@ -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
 
index 78532d6fecd71e6e04ff0f7283a458d1285eb1d7..9624b40836d40075417389b7e7340bf1bd5a42c4 100644 (file)
@@ -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
index b86116cf0db905ff3e6c18f82da190a6d50e2a96..db198d058584d06203860216abeb5cc43b1ab074 100644 (file)
@@ -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)
 {
index 10cd41a8129eb62c4589edfddbcfd907cf264b36..277f71794e61adc9016212de3f9ae05efb87fd1c 100644 (file)
@@ -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 */
index 6d3467af205d238617dfc27088cd8292eb04877b..7498bc77fe8b8e69e5dbfe106dd24861c3a2c203 100644 (file)
@@ -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)
 {
index c8e1accdc90ebe71a7c8850bc6756a2d2312f18f..22b0979206ca08b7cd929eee361607f802561af2 100644 (file)
@@ -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
index f596e1e91ffd62ce524791d5e5bf3313830c08cf..228b850e632f6be77894b9d75a7162a105fd6889 100644 (file)
@@ -364,6 +364,51 @@ u32 prm_read_reset_sources(void)
        return ret;
 }
 
+/**
+ * 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
index 701bf2d32949587e9f13974b4d03ba177a277b0e..e897ac89a3fdcb7d4908fee850e5944744eb5e1c 100644 (file)
 /* 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
index aa30a3c2088303f4964d029ab6ca2faa5e096240..93d102535c852d66a2b772b85b4d77e980a2ebb2 100644 (file)
@@ -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"
index b0e77a40704773a190b4510e496edf93cb1d61e3..b9753fe27232dd4387bfa324640670842a68c5ed 100644 (file)
@@ -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",
index a8795ff19e6deb6f415ee01b584fb0047e40e27b..c5a3c6f9504e79c8085e12e0aac10904a5177ab3 100644 (file)
@@ -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
index 75878c37959bff682bfdefca0548afb001891734..49ac7977e03e5457e3c4855fb60bc3c3f76cdc9c 100644 (file)
 #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())
index 478bf6b432c42c5c92f5329311e94ac12c5d023b..91c8d75bf2ead7759b7d19d3eb7a569c8e89422f 100644 (file)
@@ -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,
index 5d8eaf31569c6ebbcaf35a73f5270cb78c07bc38..75bc4aa22b3a0963d0e6ed468fecc5e17257eef4 100644 (file)
@@ -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,
+};
index d70b930f2739e22ce726a93474d104684409a480..085e5d6a04fd088c5422235478bb012861a96078 100644 (file)
@@ -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,
+};
index 7283b7ed7de84ace8a84d66d0436d317805d81ee..a0ce4f10ff13ea342de9ff713b8af5a15af652af 100644 (file)
@@ -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,
index 63afbfed3cbc2dba4f8c7ef0f9d9661b646b5e97..261bb7cb4e60e20bc58cfa72ff030e5655676fdb 100644 (file)
@@ -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
index c3115f6853d40414af8e6f8fa6982bedf9529ece..48b22a0a0c88e58d851ca9056ed8b55fa86f5812 100644 (file)
@@ -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"
 
 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;
 
index 85241b828c029e45b2f494925af3a3296cd92982..a3c30655aa300ee6ceb5daa02a8fcd6abfe4de6c 100644 (file)
@@ -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;
 
index 7c155d248aa3b5b1dc62f8e1bb8fcc8adf98c221..0fdf7080e4a641002796a0f9fe34b76c363b95c3 100644 (file)
@@ -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);
index bd89f80089f5b2c1e32cf6246ed43a82dad4ca6d..1914e026245e0464f77d9bd49d6c4aba29fefb3a 100644 (file)
@@ -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,
+};
index 8c031d16879e8b833c281be6267a88ced41bd38d..e62f6b018beb2379ad5dde520cfa84fe6e39e454 100644 (file)
@@ -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,
+};
index 6e7dc9d0cf0ebee796a953acca878822b245dff3..eecea2a50f8f893bf79ec5f4727e005dfbd19158 100644 (file)
@@ -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:
index ee99fd56c0439f5bdc22152fa2c530282424fd70..6b72d5a4b377981eca1944ecd1f07a0d51871bd4 100644 (file)
@@ -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
index 99612fcc4eb20e3c1b822b48b7b407cbf2542029..28376e56dd3bd3ba30924e71569f739e19786534 100644 (file)
@@ -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:
index 4a963467b7eeb46b272d13dde73ea652473961d9..973b87ca87f4a065fd212090ab67eb68fbfe5b73 100644 (file)
@@ -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,
index 63aaf076f61198cb6cdad6e69a93c443b46eaa5a..b23dd1b106e8a6d132578097aba863d48750a18c 100644 (file)
@@ -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,
index 393c0f1ac11aa38c5921827b9e6229ec61bcea16..a31d5b83e5f77f9218f19b959ea5ccb0f6d0be39 100644 (file)
@@ -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)
index 379fde521d3704cee3817aff65e01b7390f0bf3e..0606f2faaa5c5261eaa916fe374aa21f7bb5da4f 100644 (file)
@@ -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,
index 60627e63a254671ffcf9bd49d098695ca0d31842..724755f0b0f5b0b9ebfdf00b4bdd7ccb8930cad7 100644 (file)
@@ -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
        */
 
index 701f421de1a8c9c44c333590835b366d1fc73f51..cdde249166b5011cb1d075fed3caa212963427d5 100644 (file)
@@ -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,
index da1a771a29e9f1493ce192d35fde34f6fa23ed01..574a9eef588dc4b6fd764449d3893811e27e7c3f 100644 (file)
@@ -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,
 
index 96ea1fe0ec94a9d3b0393704b9bf63cbd63bf89b..1af823558c60509d571ee0024b9fca2492496ba4 100644 (file)
@@ -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,
index 12748b6eaa7b8af25e6ab9033a535e61cae98326..62526ccf6b70243be2e6e4c2f5834b7a87f0aedb 100644 (file)
@@ -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,
index dba7384a87bde67d48256dd3e0a95cc61735be55..9abe95e806abfe3bd9a85bc6eee3cd964d9d92af 100644 (file)
@@ -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,
index d9c99fcc1aa7fa97e81b1d930e2523457128f836..f1f3bd37ecda7d53db021a9f69d1cc3432b3159f 100644 (file)
@@ -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,
index 4cdb5bb7bbcf024613689228d746b914c9140de5..6bc8404bf6784cfee3751eed9e6fdd0f24b18152 100644 (file)
@@ -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,
index 4eddca14ae07db254083d883bc64aeed1b402713..9255546e7bf64fb98fce8bbfb3bb7830ce51f2cd 100644 (file)
@@ -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"
index cefdd030361d21fe2120626ccfc1e1f2b726e951..40657854e3ad4df46e1ba8be843f7fd88260bf82 100644 (file)
@@ -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");
index 499e6e3766660817fef28cc9022596ab11633dd3..5353adf6b828a55446933e070968c9b4bec20a94 100644 (file)
@@ -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);
 }
 
 /*
index f274252e470521bda095df8a2a8c2ee3611ccddf..3f56e70795b7aacb0608307331a2e4ca8a7b3310 100644 (file)
@@ -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 = {
index 69f7f464eff84bb4446e76500e627d5e03e12d78..449f9289567db20a919dcff45d68bfafe193fb68 100644 (file)
 #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
index 9ff6f6ea3617a4ed29dd19b0349a21e5715c38d6..b442f15fd01a8b7d49b14337c68896486da66cce 100644 (file)
@@ -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"
index 11a74db51e5d4f0972e9b8ad093da3fb5844aa70..0816562725f64c61b72744ecd1b88af350828d01 100644 (file)
  * kernel is loaded. The data is declared here rather than debug-macro.S so
  * that multiple inclusions of debug-macro.S point at the same data.
  */
-#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 (file)
index 44ca7b1..0000000
+++ /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 (file)
index aad1a2c..0000000
+++ /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
index 27725750ca3e3ba9e6328c4fae8a45bc50637086..485003f9b636cd266c86a37db98bd0c62cecd984 100644 (file)
@@ -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;
 
index 7d09f301b3a179d8a41f9573730d07cdb4d3bcf7..bb9c9c29d1811026f2ac15d5fee2154ce0095fa9 100644 (file)
@@ -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));
 }
index 53151030a07d5962c479fc9d0a7bec0bd3bb4464..db8be51cad8017d5197fd27cffbef5f7ec56664a 100644 (file)
 #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).
index 0cbe63261854b644a57e2d6a8f35c23ce9511c0a..501952a8434455af70aeea381aeb6cca63b7d6b4 100644 (file)
 #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
index f18fc3ab4e58a337a285a8b57ffd0b341645d156..53d085871798ef62afca5f3905dfc288f8ca8f34 100644 (file)
@@ -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
index 6ff503536512e09e168db98f9c2daee18bd72e3d..e4863f3e9ee7a05367d6f8fa7c34b03fe72a7f0d 100644 (file)
 #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);
 }
 
index e8c3f0d70ca66efa50d71bba32c462829148df4d..5dea90636d94f91e10820a41a502f23b796fc522 100644 (file)
@@ -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
index 33631c9f121802d447ecd38fa7f6bee4af955e18..7209db7cdc721b520c81fdb093c7b697a362c214 100644 (file)
@@ -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);
-}
index c34d4efd0d5c46987775b47c1393349760d60c27..0a3f30df1eb8cb9c45d375b465fe2a94ef8df6aa 100644 (file)
@@ -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[] = {
index 9c8e4a9e83eeeb6245aef10421d6824e70fa7d9e..051b62c2710208537a3442a0ec03af57c11cc530 100644 (file)
@@ -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>
 
index 8c979770d8728b83ac75330e597135a3d78a57b7..564f57d5d8a74464ef3898b0086e2d8d8305d0f8 100644 (file)
@@ -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));
index e6ad161449dac160a55f4afbd899ac6123e9a2be..d453522edb0d66b0488e46247fa4446876e69f6f 100644 (file)
 #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
index aca39a68712a6a09f77f8cdf12c842346071d839..eaa605f5d90dc463ac62079e01d5db92e50473ca 100644 (file)
@@ -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
index 5c5ad70e48be2f37b134dec4cd36534f38fd4477..db0bb75e2c7620e9a7964c40d6a428cd66f9d4a8 100644 (file)
 #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
index 1f3fbc2bb7768a4389e8c7796affdfb65f521d1b..721e7b4275f3bc6496ff4ccb29fc419b572719f7 100644 (file)
@@ -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)
index 692a77a1c1536eb045b714559b17d0e68aac78de..16b5f71e6974d5cfee37dc7b64739946c3683f1d 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/platform_data/pinctrl-nomadik.h>
 
 #include <mach/hardware.h>
+#include <mach/irqs.h>
 
 #include "devices-common.h"
 
index 91754a8a0d49003c6abd723314ca046af0897a07..318d490208948bc1a8a78041f878837d07d9315c 100644 (file)
 #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"
 
index 3c8010f4fb3f355f75d313bddc5ddd54fc5f6e51..4b24c99926541d149d055fbd891588b1ccebdc91 100644 (file)
@@ -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;
index e8928548b6a36682031f7c88bc6c2928390f4ac8..fc77b4274c8ddb59b4f25c06515d886832cd344a 100644 (file)
@@ -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 */
index 3cc7142eee02b77480ebf987c74a3b217e5915b7..9991aea3d577d7dff57481f823b25f521af34903 100644 (file)
@@ -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,
index 6f39731951b051a49213eafd32ece237904f0638..875309acb02272cf76c405a72a319cf29dc16b6f 100644 (file)
@@ -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();
 }
index 145482e74418d74f2198e8a4c0711cc824f17c75..78ac65f62e875d33c38360d692943f679575326b 100644 (file)
@@ -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 (file)
index 0000000..465923a
--- /dev/null
@@ -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 (file)
index 0000000..2ed0b7d
--- /dev/null
@@ -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.
index 2b2419646e953d29803875036cc3fcf22af2e723..6f2b843115db96e50ecef39b189228d5983ec0a2 100644 (file)
@@ -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 (file)
index 367d1b5..0000000
+++ /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
-
index f8f9ab9bc56eb06e3e85b80fd3dfed94b6db3d4b..b9cf5ce9efbbbe7d5557b4cea3c1952095d292a0 100644 (file)
@@ -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
 #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;
 }
 
index a5bd28692b06e96eae2c8a3cf2339d81ccd9b796..3c66d48ea082dbdcc24c8162711e6f52eca64a47 100644 (file)
@@ -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 (file)
index 0000000..adb6c0e
--- /dev/null
@@ -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
index ba8d14f78d4d2d7f5bf260991ff32b50f23d96d3..e16d4bed0f7aaf1e1d4f7f3423cf2c0a35fd41dd 100644 (file)
 #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
 };
 
index a009644a1555f52e61d8630ae2988bc4d52b2c56..954b91c13c91ef341ad52ea44813057ce2014842 100644 (file)
@@ -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 (file)
index d558d8a..0000000
+++ /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 (file)
index 5fb04fd..0000000
+++ /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 (file)
index 6c0245e..0000000
+++ /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 (file)
index 5c47c97..0000000
+++ /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 (file)
index af4e844..0000000
+++ /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 (file)
index 1b8bf0e..0000000
+++ /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
index c2c96cc7d6e75e5b8747faefa4f97d234d2f4966..de3df283da748fcf8acd47f53a26d096caf66995 100644 (file)
 #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
 
 #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
  * @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,
-};
index b6f305e3b9085fe932ab056d2a7a68aa3db0f738..a34f1e21411672feea380b14471652edcf459cfc 100644 (file)
@@ -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,
index 7fa2f7d3cb90a4329f2f844b6555a9d81a42f3a8..afb84621ff6f210eb390c37fdd929c66cc32cbb3 100644 (file)
@@ -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
 #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 (file)
index 19f55ca..0000000
+++ /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 (file)
index 37c7cdd..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-# arch/arm/plat-nomadik/Makefile
-# Copyright 2009 ST-Ericsson
-# Licensed under GPLv2
-
-obj-$(CONFIG_HAS_MTU)  += timer.o
index c288b76f8e6cf1e0b372fe8f98b036a137cf0591..37a488aaa2ba95dffef6c017988df5fbb4769af5 100644 (file)
@@ -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 (file)
index 6f506ba..0000000
+++ /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 */
index 1867944415cab925e2817174b8d8bd0d216c5863..8db0b981ca64f2b368e3fed396637c0957869791 100644 (file)
@@ -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;
 }
 
index 0abd1c4698875f4edbb5be3cd506206c676019b6..ba3e76c9550489d18a50c8b9d4931c225c5edb73 100644 (file)
@@ -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
         */
 
index a17d7b3e3725b6fed6897383e880720643aa8cb5..51afedda9ab61fd761114d79422fb2e34d6e138b 100644 (file)
@@ -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 */
index a9b8096b8252b04b4c50849c93e9b7ee8a26ed52..87d501ff332852124b48180793f3d7e86ef2bbe6 100644 (file)
@@ -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;
 
index 1fe6917f6a2a75e9f36cce7c28f46ef13228f113..dfd8b7af8c7ac93db4bf6d3d28371a072793c1d9 100644 (file)
@@ -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)
index ac13227272f04c92dccd8b7a5933424889e0e7ae..e6d7c42d68b637e58e20b0186b7326df8a2a279d 100644 (file)
 #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 */
index 61fc53740fbd8811a8d06659806ecfc6e5cc8c77..887a0c954379d7759a4108df9506dcf87ad49abc 100644 (file)
@@ -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
index ad6089465e2afba33b49cc1def128c3c0f9a2cd5..5ec104b5408b37d58e25efa202439110150a21c2 100644 (file)
@@ -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
index 23557d30e44ceb9e6124f4cb19b9851325db67ea..bae56131a50a44e7dc7fff38beef9cc8e9d7cbe2 100644 (file)
@@ -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)
index 202d71a15be1125109f560175a9137fa62064050..e40c9bd7914341a4381b06b8d13f2a0162f1cfbc 100644 (file)
@@ -82,7 +82,6 @@ config PLATFORM_AT32AP
        select ARCH_REQUIRE_GPIOLIB
        select GENERIC_ALLOCATOR
        select HAVE_FB_ATMEL
-       select HAVE_NET_MACB
 
 #
 # CPU types
index a473f8c6a9aa2be66f04f375ef7b7820b7c0683a..486df68abeecc955757a352cf64e70ad9b39a020 100644 (file)
@@ -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
index 101b33ee9bbab914d75a7e2295feb6a57290aafa..95a4f1b676cead2006dfa3b44280020b4cb248ab 100644 (file)
@@ -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
index 342e378da1ece760b2c2b3531780cad9b897b95a..1f3b3ef3e103fbe3581670a62d03db2c5da9e153 100644 (file)
@@ -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",
index 7d345947b3ee271f0bc9d5206431d419d56f470c..ca2675ae08ed95d1c3de56ad0a507af390b348e3 100644 (file)
@@ -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.
  */
 
index b31e9984f84964570b16e743892f4432af730269..fe3cdd22bed4590315268c156e28076c26cff238 100644 (file)
@@ -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)      \
index ae52825021afd98237557656abf77dad4a75491f..b681b043f6c819fedc4b819c5ffa59a72cd7059f 100644 (file)
@@ -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
index a5b1d7dbb205389eef5e2d5627f0aad3744778fe..871f89b7fbdaf08a0629679f01d804337804cbc7 100644 (file)
@@ -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
index 4fb63a36bd52ff0333f9d849a0a75479008aaa5e..f6084bc524e85e578487d34dea06f0e23b4a8214 100644 (file)
@@ -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;
index ec4554e7b04b68ab4c41ad93e612469ac896708c..90a2e573c7e679ac92300734e3641f7d5d5b45e0 100644 (file)
@@ -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
index 41fc28a4a18a2305763db7be6e0d51210671030e..23d6759bb57b8dd6af9a824e78ce7335dede1d80 100644 (file)
@@ -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
index 8b3a9c0e771dc3926131b428ba2472a337d41845..0a88cb5d316db2d1ecee607eabeace897857cdad 100644 (file)
@@ -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.
index a15f40b527834256eababa34dd23d076cf003e2d..5e7088a26726cc0133ae3a6f166f3597832646a6 100644 (file)
@@ -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
index d1be684edf97925331569d9af422a5f427e2a271..285da3b6ad92c440dabaec8dfbeea9b8ccf6613b 100644 (file)
@@ -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
index 3384a5244fbdc147155278729ef979eca593c3b2..0663067870f2a9166dbdacb001cbeefdb97b37a7 100644 (file)
@@ -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
index d43ceff5be4782b7024ae0f04ad73f278d4d7486..48a4c70b3842276486d88179b1919917106e773e 100644 (file)
@@ -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
index e9f9ec8d443b5b959ef4b164b0a46197cad7ebb9..e80d585731aa8ed8d2e89597e2ddeb65150ce036 100644 (file)
@@ -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));
index c5ed59549cb878c211146c8ac86c8eaff354c525..17307ab90474271e4c77f9d48bfb775f2049db74 100644 (file)
@@ -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
index 4efd9185f294643d28aefe755c52c9d52e071f84..b14ee53581a9674fc53cbdef9555dbaf0513897e 100644 (file)
@@ -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;
index 139df8c53de83374a86189a8278d91a184d3e26c..e6ed0d897ccc7c8b4f08b2f12fc97edee223de1b 100644 (file)
@@ -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);
 }
 
 /*
index 820463a484b8dbc5b21ee627822297d4a33bf91f..af5366bbfe62727b09e2d47474e78a7483bb3a13 100644 (file)
@@ -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
index 96f24fab7de6ee0e559369e195a2fa7b5120a8f2..47b3bb0c04ffc4f9db8395a6042235a5c7fab105 100644 (file)
@@ -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);
index 35932a8de8b8d299fd7aaebcf31d56eb7c6db6d3..6ab3b73efcf8d4304d0b832d4d398f94a0f332d5 100644 (file)
@@ -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 */
 
index dfc1b6f2fa9a4b70f251d8766c773c39fc7733fe..b95e76caf4fae24e0841500cde288bcd775dbc5f 100644 (file)
@@ -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
index 339cef4c82568a13ac20de767f066a6e1d95f035..81d5cb9b65695034e27a34b866d2a4c55389c673 100644 (file)
@@ -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;
 
index 6796499bf789b0136a79a066afaa44a0b901f072..01791c68ea1f1330894e71f41f1ded0131d82e93 100644 (file)
 #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 */
index e62c223e4c4594c3c06c762352d8e61a975e2d35..95983cd21e77e45a47be44ea41c82b59479b9c25 100644 (file)
@@ -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
 }
 
 /**
index 90f346f7392d68df68844fd24472f7d5af8b1bf9..d48a84fd7fae51b298ee1b03956dd823dd82ffdf 100644 (file)
@@ -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;
index 4ebf117c3285079d7a4ca0d9a4cee8b311b9e16c..bd9ada693f9561ba15b581855d1b80c95f57db4b 100644 (file)
@@ -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 (file)
index 0000000..bd65dae
--- /dev/null
@@ -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);
index 6dce9fc2cf3c131ce6349a291775441e0a3f5c43..e2059486d3f84b9bbee412c809aae8acfb21056e 100644 (file)
@@ -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;
index e7f1a2993f780ab89795a73c8b2e9bd71bdd2ed6..ec37e185d20d82333c7e4f46cce5d721b99d98c2 100644 (file)
@@ -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.
 
index 1b52c2c31a7a284c8e4f6b6d08cc53faa60da42f..d9ff4731253bb6e8f6402686e2401e251126ecb2 100644 (file)
@@ -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
 
index 639dc96077ab815addab3a43bc894e5654fe6bd9..d697b08994c916dd40e6eabb593fb28e67cd6135 100644 (file)
@@ -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
index 5f73ce63fcaeb79a6a10d7d77b92d82ad26331db..42b1f43b943ba197ce766067d735c47397519382 100644 (file)
 #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
index eedf427c9124f3c7fc4e13d5dd293b41dafd5f82..3e13e23e4fdf8a4e3fc84e07ef091cffdfc0492f 100644 (file)
@@ -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 */
index ae20ce1af4c739e9085f3e53caf421a35f41c529..6e909f3e6a466972285aa2797fd315b898313720 100644 (file)
   *
   * 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
   *
  *   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
index 3d5179bb122f120e24477c3be6f1459182b8bec5..eb0b1864d400b2a01386ed3a77fedb300a560227 100644 (file)
@@ -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
index bedd12e1cfbcc0b636eea99f1ca18728938ed2f4..0733b05eb856b05476621296b45fbde7661ef6a8 100644 (file)
@@ -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") ||
index 2049f2d00ffef60f0e7b1f9cfa5fc9cbd25a1758..9db8ec07ec94ff4d953bb7277d1698304e39190c 100644 (file)
@@ -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);
index d183f8719a505ce18e4cc8cb06ee4df3e8fa8674..1ca045d443249ebfa344dd01b15fe8f937f03674 100644 (file)
@@ -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
index 5829d2a950d48e4150b9c51510835c983a8854ad..cf9dada734b65ca2506444c6b00ea46b13b0314e 100644 (file)
@@ -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
index 1fc8109bf2f94761d01c21eb1f9358d58668aeee..8a5dfaf5c6b73fc94c7ceab634d1bf679a4f06b1 100644 (file)
@@ -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) |            \
index dd1130642d0753b217e9a73c3e9404bb2aef2d0d..e834f1ec23c8a4ad16c67b0d3349565e1813cf83 100644 (file)
@@ -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);
index 028470b95886d0085a21416b4c64e6e179e4ec8b..a51cb07bd663debc0b9f9fb17211e0a57cbed1f1 100644 (file)
@@ -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 */
index dca213666747fecdc6d261f33adf5fbfbe294b05..e56bb651da1a1e4929c6047a196e6878d537581d 100644 (file)
@@ -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
index d8b7cc8a66cad141e4c9d58b23540427a4771167..8e299447127e108a7d0b8179fa085a8b245f8dbb 100644 (file)
@@ -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;
index c4e630576ff283666f74c37ee985cf4f1b22b105..31036b56670e6dc18e21a976e7632ccc57d78d4e 100644 (file)
@@ -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)
index 69718cd6d63503e657a4878a1277ab260fa44bf7..436d07c23be8febc9ad245fb73e4f1671a004cd9 100644 (file)
@@ -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
index 6cba0a7068bcf9f713a1ca79a233211a928c771a..d71a0bcf8145d529208ff9d053e8b6cb497eb45b 100644 (file)
@@ -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>
index bea1568ae4af1aeee10008fbf1ae110dc6fa47ae..c83a937ead00676eefef950b6c00d77cd644c8a9 100644 (file)
@@ -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
index 28368701ef796ff5c4268398264cdfb504a0be84..3109ca684a99f31c3a52613e3ffd2f291d6f185d 100644 (file)
@@ -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);
index 9195fd80e11ed7efa2e030704eab0b22e161c7cc..65a872bf72f9c693039540519b69f9c8238b7214 100644 (file)
@@ -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.
index 851fe936d2421a14d7a558e2946321503d73a5b6..e3cf9f682be55e5d07617a7ba921bead05a218e1 100644 (file)
@@ -2,7 +2,6 @@ bootsect
 bzImage
 cpustr.h
 mkcpustr
-offsets.h
 voffset.h
 zoffset.h
 setup
index e87b0cac14b5e5d735ab21f9f3b163db52349938..b1942e222768e7c9c2707c14dbdbd9643a51a8b9 100644 (file)
@@ -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);
index 2ad874cb661cef0ccd4b42cb918004141c28672a..92862cd902012b9fb174d03e6e2cd687787136cf 100644 (file)
@@ -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 (file)
index 0000000..1c6f7f6
--- /dev/null
@@ -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 */
index 6e41b9343928941a82533d4fb299c8b70aaf9add..dba7805176bf3cf705b5308d6c7d13b5142f9a61 100644 (file)
@@ -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 */
index a65829ac2b9a1b4cb9517f94318bc106291061ad..9c2aa89a11cbf8d4a124d25bdea25d726cedba17 100644 (file)
@@ -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();
 
index e4c1a41845317b1f91a72774474d9c2a4dac9293..726bf963c2276569c39c67377b64fd7a74fb539e 100644 (file)
@@ -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) {
index ca45696f30fb8a01a4d6852388d08ab19d4bb778..c228322ca180f51521175adc2d393ad4e718623f 100644 (file)
@@ -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..
index 8573b83a63d037bf2f7eb09c8922b94c2b535c45..217eb705fac073188fb18e908b675340834e1f97 100644 (file)
@@ -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
index 520d2bd0b9c583de16ce246ffbf938c5c9f48b33..d11a47099d330d1dcdc21261df571212551f3f03 100644 (file)
@@ -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;
index 3af5a1e79c9ccc5ebe98c64b3af921562f397141..ee0af58ca5bd7e5e75ae22885a887ff86381fe46 100644 (file)
@@ -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
 
index 192397c98606690f34d1d510052738f04bbdd931..0c01261fe5a846bc2500fc24c1ff56c2b432e86f 100644 (file)
@@ -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",
index 720e973fc34a31b856998715165f7fc50ec9ec6d..1b1dda90a945ede1550294e83dfc51d7a2f9f663 100644 (file)
@@ -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 (file)
index 0000000..7307d9d
--- /dev/null
@@ -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;
+}
index e36c681849205cd728bbc59b5903c87f61a81a73..38079be1cf1ebc98fa6d9a61aebd59ff81822f78 100644 (file)
@@ -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
index 0df024e5fb63fe75ba828fd3d4a847beb22ecb32..d09c6b4bab2c9632cf2bfa88ea5fb8ed196e10d4 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Module Name: dsopcode - Dispatcher suport for regions and fields
+ * Module Name: dsopcode - Dispatcher support for regions and fields
  *
  *****************************************************************************/
 
index 2ef04098cc1d5f4d01942d3e4de79014c4911efe..a1dee29beed328430491bdbff3cfe386692b06ba 100644 (file)
@@ -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);
index 23a0324901307b9f0c930f7be00beeff45dbbec0..68a921d032475edbaa7740d9f880ee5bf52a8db3 100644 (file)
@@ -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);
                }
index f70b9e5fc1b59098b530e58567bba2ae36ea99d3..7928d4dc705618a833ccce3172ed5113307d4cff 100644 (file)
@@ -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,52 +502,10 @@ 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
         * -----------------
@@ -554,32 +513,36 @@ static int acpi_pci_root_add(struct acpi_device *device)
         */
        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);
index 98510931c8153110ee0617457fb63cafe652696a..c909b7b7d5f159de1d6632284a9f6358eaf737a8 100644 (file)
@@ -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);
 }
index 169fc58427d3cefc343c2e1ac229a5c2c280655f..537ae53231cdb7a613a99aa1d40f6dd0294527d9 100644 (file)
@@ -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);
index a4c3ebcc4c8609de39d7331d23b24bd830ac77cf..dc96dd8ebff29c573960b475c2a664e359edc2fc 100644 (file)
@@ -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,
index 9042781edec340e932e39d2b75c7dba495764e42..dbda91e4dff5189ccabbb710b7a2a11f0e099651 100644 (file)
@@ -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. */
index 201faf106b3f4e342337e2219213a72c670ef447..e162999bf9162f390601ccea940cfc96d94842c2 100644 (file)
@@ -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,
index 2c4eec2ca5a0784bd50d392a84edc74911a58916..63e688393825539b5f2c64537cbefb1659c579c3 100644 (file)
@@ -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;
index cc65b45b4368aabd6d0af17897cd5e0b2b857c31..792daad28cbc6fa883a2e20911b33dbe840a49ba 100644 (file)
@@ -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;
 }
index 9baf886e82df39f710b897a0b864824fbedfebad..e6b5c89469dcea0fd7dec00809934b54eccafcbe 100644 (file)
@@ -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);
index b6b4b5ebd4c2560255b3a53bbceae0a814723e96..98fdc3e014e7f5ada5dd70cb26a511632d4d6acb 100644 (file)
@@ -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) },
index d865470bc9511a12f3c4370dd12bf22c28fc2cf0..debd4f142f936b084ff7d92c517188d7728cf332 100644 (file)
@@ -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");
index 0d546b64be341239a5ee405970f166be47f83081..4adf9ef9a113010e2b8f51cabd27e07c57898c83 100644 (file)
@@ -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);
 
index 3f4bfc814dc7d5a0382635dbe16a41af413e59fe..9959d4cb23dcc2ddad7deefa008def72ac513925 100644 (file)
@@ -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;
index ee82f2fb65f0ab2c76135416ac8547f1d9c1fa3c..a1d4ede5b892d4516b294f91aca91633864e7d43 100644 (file)
@@ -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) },
index c58ea9b80b1a3b63e65a52236d71c8db4cfa02c4..c5a0262251bceed1a0f486bfd76ece26ae5106a8 100644 (file)
@@ -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).
index a0c84bb30856073aa7a46c52690f163789bbd9bc..053201b062a4cffce40422ad1e28c925d4ea5244 100644 (file)
@@ -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. */
index 20ab5b3a89150954cab2ec442b4f8b4ce93234a9..cfdfecd5bc763026762bd9e26b08e4e3c15e7b67 100644 (file)
@@ -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,
 
 
index d0d824ebf2c187d492f29daef8bbf1043f56d7f1..1cd49241e60eb5024ac2941a5b0787fa46f7c13e 100644 (file)
@@ -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();
        }
index a96bda3d3b845f8715a6b66a6f840ecc99d2250e..4e1ccb1e6614940ff4b927642e6881dca19d3350 100644 (file)
@@ -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 (file)
index 0000000..37a3051
--- /dev/null
@@ -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);
+}
index 7d0e0258f204f031617010f623292ee3f16ddb87..6b889a0e90b325460f1bd555a40f56a23b8dafb6 100644 (file)
@@ -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
         *
index a0985732f1e244b94247a8ba14b0717189db38c1..7fdcbd3f4da5a7756f2f1fb01a467a11b107092b 100644 (file)
@@ -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
index 36f06de4c5ab6e80a98c778db0595e3d74cff5fc..f93453d0167305d7633495661a5f92d7720aa32a 100644 (file)
@@ -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
similarity index 93%
rename from arch/arm/plat-nomadik/timer.c
rename to drivers/clocksource/nomadik-mtu.c
index 9222e5522a43e97236c86f55c28006c1bea3a8e2..8914c3c1c88b08d8c183a23b17f1e2bd1ffb1e06 100644 (file)
@@ -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
 #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);
 }
index 649a146e1382b61b3143493125eb79d38c63a894..e66e8ee5a9af0e59e6599bc3d637807ee99a0466 100644 (file)
@@ -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 */
index d76fe06b9417d64a733849f3b961d6d358ab6336..1d75e6f95a5877fab7c987dfe5b50bf2d8394017 100644 (file)
@@ -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))
index bc615cc5626674065e5439435c11fc80d08f7e17..8bc5fef07e7a797f7cdde6e8f3f15445afde4993 100644 (file)
@@ -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>
 
index abd9038e06b1351ab7706c81fcbd96e8dbf2eebd..d6668071bd0d4cfca02996978818d65a62ce7630 100644 (file)
@@ -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);
index 7d35c237fbf13f6ae2bf7a44e330cf60f24ba8d2..5a31264f2bd176a57c0e221317f8d7efaa9184cc 100644 (file)
@@ -19,8 +19,6 @@
 
 #include "virt-dma.h"
 
-#include <plat-omap/dma-omap.h>
-
 struct omap_dmadev {
        struct dma_device ddev;
        spinlock_t lock;
index ae55091c22728a4342af8b3f288ecb4b013628c2..23c5573e62ddd1d6b8aec8be10e9f47bcfaad39e 100644 (file)
@@ -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"
index cad9e1daedff4ec30aa6e304c2527073674fe020..851ad56e84097b7e21e73ce5bf1a10f42d05f7bb 100644 (file)
@@ -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"
 
index 6cbb7a514436fd0b355e38a2d6138a65254f147d..2d864b48a48f81ade5818cffb2f3825628020d6c 100644 (file)
@@ -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"
index a9a347adb35351a3b04b2e3a089ff6ecd9f0ef38..2cc89ce745c9b432e87920b5499a0c8f50cd2e0a 100644 (file)
@@ -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) |
index 08c674957af82dfffef5a8a5a2c2aba8a9fd0193..e7a711f53a6f7cd8f0b1316d324034b1ca2acc1c 100644 (file)
@@ -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]);
index f25610bb31489a2ded669112c2b2915f826c4de6..6ce6e07c38c1b3ba038ee816e26225e8b5f9ee4a 100644 (file)
@@ -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.
         */
index bb1b392f5cdacd1194e9af1772469c834e4192dd..1162d6b3bf8561d6ed1cfe399643dff6deb4027b 100644 (file)
@@ -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;
index 14a6c2913e490e2cf72cd05173786582b9ada5d3..bf892bd68c1769fa35de808fcaf54e739fb142bc 100644 (file)
@@ -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).
index a006f0db15af78a536837e76fad021c12c4fb8b2..01f7fe955590c1b79a64cd088431858b7d9caea8 100644 (file)
 #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()) {
index 219942c660d7d2129e7c21ac375761dcd5309c9f..5d1d21a6dcdd11b20bb57637a333e83d2382bbbb 100644 (file)
@@ -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);
index 81e6a568c29debcf49bb915c5d3aa19bcc88324e..cda01f808f12664d6226cc71facb64ed396d41cd 100644 (file)
@@ -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);
index 47634f27f2e5eca62cc6335d95fc246e13a6deb2..ebd69562ef6c802af7956dd168de29bf27f6f19f 100644 (file)
@@ -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
  *
index 4422d630b33bc4052ddfdc311ea37944f9d87051..010156dd949f392c9732f7a1b63ef0f67de26bd2 100644 (file)
@@ -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);
 
index 1630150ad2b19e1cf362881ff91e850c044e72d5..e7d6a13ec6a623ab1d4123d80a4aae37bb76aaa9 100644 (file)
@@ -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
index cef68ca859d335e7a58853a7fd55dc898b9c825e..b62215716b2fd66fda16b0084f077927a8c3f02f 100644 (file)
@@ -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/
index fd7722aecf77929eea158263af6cc1b601287408..d0f7662aacca05caf3596c9edcc8280dfed675e6 100644 (file)
@@ -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 },
index f4109fd657ff7a337761f9029969dde8ee71e3cc..eb2ee11b6412ac43e9baa08596b881d92c8430e3 100644 (file)
@@ -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 (file)
index 0000000..1d6565e
--- /dev/null
@@ -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");
index 9d7a42857ea190a9b9fbc12582582b8ae97ebd2a..4dfa605e2d14417203e734c4a68dc2447e86f5c2 100644 (file)
 
 #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
 #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
 
 #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
 
 
 #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
 #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
 #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
 
 
 #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
 #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
index d917c0d536856c80b7b898c7ad950b4728c16db6..21b196c394b197d222e0d1f58ac52f37d65b3e5d 100644 (file)
@@ -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[] = {
@@ -298,6 +310,9 @@ static enum power_supply_property hidinput_battery_props[] = {
 #define HID_BATTERY_QUIRK_FEATURE      (1 << 1) /* ask for feature report */
 
 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 },
@@ -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++)
index 7867d69f0efe1cd734c57e7e4627eb9aaf7a367e..61543c02ea0baf42c58fbfa5518dba229cb22901 100644 (file)
@@ -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);
+               }
 
        }
 
index 5669916c294309379fc0472f4efe3ada24f60ca3..1219998a02d66e98ca11cecf0c740044b6801deb 100644 (file)
@@ -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
 };
 
index 605b3ce21638da5723e8f6ee50d9109ead4c2602..cf6896c838679d7ec5527a7cb94037e16c1fd78a 100644 (file)
 
 #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,
index f5602fec48655016ca0fabdad1b743f71c17ae52..6a48fa3c7da913e487e5aa0b1538ba5aff19bbb1 100644 (file)
@@ -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");
index 7074b2a4b94b26b955dc20b47cd570866a358cb7..af7f57e8cf3b38743892b0365bde4dfa61b07682 100644 (file)
 
 #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
index ca6527ac655dbbe6808c2f1a5e6521eefe7099f9..b8b37789b864bbeb3c4de24047658172518b25ec 100644 (file)
@@ -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,
index f82daa1cdcb949cafb20cdceed4c757880565f4c..fbb7a16a7e542fbc843fc9cb4b40b04995175231 100644 (file)
 
 #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 (file)
index 0000000..5084fb4
--- /dev/null
@@ -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 (file)
index 0000000..547d77a
--- /dev/null
@@ -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
index 1317c177a3e281404b2387f88f1decca40fa6ecc..d4f1e3bee5909eed76861acff408b582985462af 100644 (file)
@@ -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;
 }
index eada7830fa996242f417805e852b0f838080da08..beedcf001ceb5f9f23e5a3991c1974815bdd4aee 100644 (file)
 
 #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
index 014afba407e02dbe18d8b47426eebd6f5cbdb0e4..31747a29c09348a9d7ad5b45021b12800832e087 100644 (file)
@@ -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
 };
index d9d73e9163ebb4f2e8956746b88e1c6e0b575877..0bc58bd8d4f5a9e496187310326aff7e031e74f0 100644 (file)
@@ -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);
index 7c47fc3f7b2b0b28f27021c75bb3b8d8f3771c4d..413a73187d33d9f0313444f8c20288408cd001b9 100644 (file)
@@ -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 (file)
index 0000000..b66617a
--- /dev/null
@@ -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 (file)
index 0000000..832d8f9
--- /dev/null
@@ -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 (file)
index 0000000..9ef2224
--- /dev/null
@@ -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");
index 11c7932dc7e6c5628f940d141b50366ca57008ad..ac9e35228254f0e6a942845520bb542752ca0921 100644 (file)
@@ -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 },
index 14599e25679181cc00223675a7d4170cdff70174..87bd64959a91b4bed5e3745751e237f78ac4470a 100644 (file)
@@ -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++)
index 4800d4c2a7b7fc8c7634039dfbd52ee5c4232ae5..32f238f3caea852ad116fa9eab465c945fa0d6e3 100644 (file)
@@ -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
index a930f0997d25a7fe4c69ad5fa10bc1a9c42ca5cb..5da287443f6c3d007ae96b4e7a9d5d912fe3d3d7 100644 (file)
@@ -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 (file)
index 0000000..59fd126
--- /dev/null
@@ -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");
index f41502ef3f55086db9f87610b95d2acb07d72434..a23b91b0b7383829d7d6427f93e4e6dccace5069 100644 (file)
@@ -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
                 */
 
index 9d902725bac94f28c91aa26ec57615988cd96e77..b33d95ebc890aa9667d64f01a66fb961244fbe88 100644 (file)
@@ -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
                 */
 
index 1abbc170d8b77f302154323a0ea944474bfd5d37..8c4b50fd9a79b59fcb15ce254d6fa835aa9eb4d9 100644 (file)
@@ -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);
index de0874054e9faebde97690fdb23986d268cbf95d..77629d33f03f2d087e7f9c1473fdaa2258a56877 100644 (file)
@@ -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
index 7c0f1ecfdd7a3ff88fed02671e1cf0fba5847b24..104a7c3153c0c4ce5fd695403bfb8a263da992d7 100644 (file)
@@ -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
index 83fe6f5b77d120e9b3194325f0fc83879a474a0a..5ea769eda999ff1fa35954bdc6bf467c22ebbf99 100644 (file)
@@ -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 (file)
index 0000000..7a04f54
--- /dev/null
@@ -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>");
index 81363ffa5357f11213c6b87b3dc4b0d80786d6ae..6e99d73563b8abbe8b5c6931b741ab15a5536a33 100644 (file)
@@ -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)]);
index 182ecf0626c2098e3c38c4da0eeea54a1197ce7d..feafa91c2ed99088c0958059e0de6c04dd832128 100644 (file)
@@ -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)
index 89342f7e0c5b700eb302484ba5eb556ccadacef9..525471e776a76dfe468be16a9d714011ea27546b 100644 (file)
@@ -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");
index a47637be0cc558c0b2ea4ccd6209e42445ff80e5..ddec47a911a0df6ea74c1a9f5e926fbbacc54a2a 100644 (file)
@@ -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
index 334fa90bed8ec73a348fcc29d85a7db8324b1ca5..f60d4be589414149f1ca7e6f9157d37012ef2d24 100644 (file)
@@ -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
index 4db846be4369b1bd7b894e8a590437b81597ee82..4ec279ce052f0fc64f2d822b46a463fb562717fa 100644 (file)
@@ -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);
index ff5e139f48503c54e695144d6061be65ad1e1e95..7fdf34704fe5d3469f815f7c44b79f6fb8e15e35 100644 (file)
@@ -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;
index db50f788855db4f41de7f35e3aee4abe4da87253..f8e405c383a0774948c464f415ac94f77d7a5679 100644 (file)
@@ -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;
 
index be88728f110643dbaef2794b8ad64143a7224b08..592f597d895181d0ce1e5dd697a7d37ab09f2ef3 100644 (file)
@@ -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;
index a18e639b40d7e4c354812092c494e46f98618235..42ecfef80132b098735ab2a4d96bc9ec2094eece 100644 (file)
@@ -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;
index 61200717687b85b3fed040f9599ffd1987b8842d..bd8bf0953fe38db2d071cd6ef0110f6b03271e0b 100644 (file)
@@ -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,
index 5ba277768d9914c3dd6364f3d990feef55b67c92..a3ae09124a67f786c19f1e426c12ca77a06c3963 100644 (file)
@@ -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;
index ae02c84410ff5c04325444f6660125c87335dd3d..a2cd50441ca1a5805bb60c5a03bac573c0b38664 100644 (file)
@@ -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;
index a4502686e7a8763fb5aeded988f026b2a9dd1c99..3380372c0393e7262b95a611c92aa7da659d997b 100644 (file)
@@ -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
index 8b4c6d5f8f3694d330dfd50d36ae9ef870af4339..df9abe83f8773efe38eda6d6f349399ec107df4d 100644 (file)
@@ -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;
        }
        /*
index 8f22ce543cf704315399b751371d79f8dfbd2c6e..bfa65079fc38de832e3eabc8c0227ff3f9e96fda 100644 (file)
@@ -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);
index 4b1becc86e54a77d6beea297b2128236992dd8bb..993504015963bf8789f910b4532c2320ff653231 100644 (file)
@@ -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>
 
index 8340445a0ee597dfe65566d8924a1bcc482e385f..cf1c437a868794362b3dc0d2e121ee28f52a8eb2 100644 (file)
@@ -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"
index 99cf10449cf5a6090bf5c79d00bcf20ea41ef394..fd15094de34aa45005076bea18dd0025cd048e2e 100644 (file)
@@ -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"
index d3cfe65c0494acac5887c885d733ad7c2536358f..39a77f0b886066daa82aad7be5e3bf968d6309bf 100644 (file)
@@ -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"
index 5fb195af43e23696572e8debff626e5ac4a00d69..4a7d2ebdfc97e7ee7d1773f3d82672783f44dc87 100644 (file)
@@ -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
index 4796bbf0ae4e5b4fdd1476ac8e6cd4e9e43ec6c5..49e86aed2bc4f13d05ffbf5a2d094b5a979372cc 100644 (file)
@@ -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.
index 9a49c243a6ac59c78c98cd9de021429d44aa8908..5451beff183ffdf69e24d5d1ca016d11215882a2 100644 (file)
@@ -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)
index 94bdf83b4bc8c911189c055b22cc9cc0d31defe0..b63987c6ed200ec3ed447df7be2a0cdd6895d51b 100644 (file)
@@ -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.
index 127b00aadae31464cb7377bf778aef1002e0bcd9..3e27c031aeaa26fad637fadb86641851470595e0 100644 (file)
@@ -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");
index 1a6f943f733728c1cb7ac5ed2a4d190be9c98855..c784f4602a746c8d4eec1d8c4383ed4cae0a8df6 100644 (file)
@@ -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" },
index dc5691569370e0ec4872356577e22a69322bfc0e..29710565a08fca94ce90ac4f3f2feaba843276f1 100644 (file)
@@ -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");
index f123517065ec911ff6e4154aa25a3f8e1dd0bd98..abd5c80c7cf5f59c9a3adf78d188482148ecf512 100644 (file)
  * 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,
index 9f92c3b2209318c8476ff1de350b9939ff1a0015..87ba7ada3bbc8a72392745cdc3400fb541e8056c 100644 (file)
@@ -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>
@@ -98,6 +96,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");
index 14490cc785d29879f37a06ee52ffed57b8c32c9e..3141c4a173a7c8e9285931be1f330f420f0ce69e 100644 (file)
@@ -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:
index c7f62ac544ad74e2282b29b62c1c9f25e16cc868..bcb226ff9d2b7415bc567d2e855bf18ebfcc487f 100644 (file)
@@ -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,
index c58f9abcb35659f58ee9fbdbaad5c387d366ad06..158da5a81a661824a2dca0ee2a9fe93fb5cacfb6 100644 (file)
@@ -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");
index 737e4edc241bcf3d17db3f2cb21866b76504f072..8d13c6594520094c82f054628b1086bfe5cc7bec 100644 (file)
@@ -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
index 891558de3ec19d1ef67ca69751be8f06e21e480f..2de66b062f0d733be6e97751312d9f576c198236 100644 (file)
@@ -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,
index 531807dec6b398c109a1383b88c76bc82e3afcae..dae191b3c081861a52f4a75adea4dba3ded0c0a1 100644 (file)
@@ -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)
index 5c8978e90240904b2e4642fcc9c8520a838b42da..1f34ba104ef41888e19caf344c5fa8620592373e 100644 (file)
@@ -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"
index 295e4bedad960a0efe653dc893fe0f1e0270f2f1..79ded48e7427f7b868a9b419385db2263f279474 100644 (file)
@@ -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) {
index 99f96e19ebea8bd2b6704aa61c0f97da52dbb69b..00cd3da2943544cceadc4cacf6008901d1fe8dc3 100644 (file)
@@ -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"
 
index d427493997b67ebd6e3856724eff13b4b1eb5a4b..cbc44f53755a81b24960489d6fd0de14e2ba54f3 100644 (file)
@@ -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)
index e15cc11edbbe1efc31cfe38cc73f74cd95129f88..7c9d136e74bef3f725264aeef91fae32d99da168 100644 (file)
@@ -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;
        }
index 90f140a2d197f4807a75802f18671cbb1521eaba..e7a5b8b37ea3f394a4fbf6f78b47173976da0cd4 100644 (file)
@@ -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
                                         */
index 2cf084eb9d524d995c4e3bf72a6d327e5f1ea9cb..5fc4c2351478b21f98ba8ed2d2c329275e30ed39 100644 (file)
@@ -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,
index a7d47350ea4b5657d4ee9683b92d7243ea2a9361..ef2cb2418535bb3cadc9f227aff1b5884b793996 100644 (file)
@@ -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;
index f8af2fcd3d16380e29b22b927256955f67d71c5d..21b68e5c14fd24c49d606289220f51a2a9902e65 100644 (file)
@@ -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;
index bb709fd66993cd7f519186a549bd4b73e9609b3b..b56bd9e80957f0dc5f8dde896cb648e7cf939ab5 100644 (file)
@@ -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"
index 938be37b670cc7d9888b2287e5057e3b9cd0d3eb..7de59862bbe940aeddc9ac93a3c1bd16d8eac30a 100644 (file)
@@ -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
index 994b6acd65f4a2798e6e37bc4878ce2a94596025..81baefda037bfe1d9d6ceb1058162dfe0ce09d0d 100644 (file)
@@ -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,
index f2d6d258a28629e3462921d37555cc85fbdb1ccb..6a0532176b69a1c47c5992c1c4e335b991892c2d 100644 (file)
@@ -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);
index e5180dfddba54dc6918b8dbb3e2c8643316e130b..5233b8f58d773b6edb44f306f477674f05415084 100644 (file)
@@ -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);
index e5ed41dafa1b94aa234749064813c587aa79c468..d2e1c21b143f4ae729edd45312de1db0a804f438 100644 (file)
@@ -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);
index 3d7830bcd2bf83fa55346754f74c2205eae4b3f7..b374be7891a296bde66696e19d2137a47d7ffea3 100644 (file)
@@ -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);
index ee1416132aba2e1f9582b7911f67e94eb21b3084..d63b91904f829e9954596b06c0e34f48e3d1ba3b 100644 (file)
@@ -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,
index 9f3a25ccd665368b182ee9ed538cd10f3cc90922..8eaaac81f320a70040c6af68f6acabec51316134 100644 (file)
@@ -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,
index 688371cda37afc51ff125efa547e819126e4ca24..d0f6bfc45aea1fae0a824f65cb431f847e2ae578 100644 (file)
@@ -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);
index 963e2ccd10db81300748b4fac6d9dde8f084d3b5..8233e5ed2939dcfe415ee119edf8c3aaf042c47d 100644 (file)
@@ -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);
index a412bf6d73ef6b0464f5441c85df94c3ab6b4f15..0289a6d86f660d5e97f9a2f34a2d37c6d7f1d53d 100644 (file)
@@ -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 (file)
index 0000000..17fbc7a
--- /dev/null
@@ -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");
index 7edadee487bab16c0cbcf514ab59540f35cc2a41..c4bc1d2e2033214db1a20ff584d184f35d8635ec 100644 (file)
@@ -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);
index 26e7129332abc7e18bd7b27cd3f49d67976c3a16..5eaf47b8e37bc4427a7004b1199da5dee8d7bccc 100644 (file)
@@ -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,
 };
index 799c354083c4800cf738837587a202725322cbac..668850e441dcd7e3c13e901efc2cc1e0f3473f53 100644 (file)
@@ -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,
index 2b104d5f422c07b497e3fd8966bc9675b7bfe4ce..e6b40954e204d77bfb6a465a8ecc607db7231f98 100644 (file)
@@ -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;
 }
index b43e9f5d32683794508d88ea03098376abbb4d44..af2ed8baf0a3b30b9361c0376f65ec0672d7b1b7 100644 (file)
@@ -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;
index 48b3d62b34cba9021373091aea34049bdc608bde..7d1748575b1fffc45f38351ea3f071269545548a 100644 (file)
@@ -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,
 };
index 03df9a8f2bbf0c9a444c045a979937c501e38c4a..92f73c708a3d7c3ec80133fb4b2f05872fd11849 100644 (file)
@@ -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"
index 5c6d412bafb505f0379ca0ae7f3f2eb5691ad8c8..036a326836b29871d8710f23f5e2d57a6c02ac52 100644 (file)
@@ -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;
index 075a5457a19067c217e6c9fabee75b0d425a90b4..5c2f3fbbf5ae8fc4028ecf0fdc50ac03e92fd21b 100644 (file)
@@ -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;
 
index 23ed6ea4c7c350cb9a232d15e8a9d792a9e04cfa..37b0381f532e6458e13b7a424330047aec368e0c 100644 (file)
@@ -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);
index 6525dbcca4e3c6d4d15d0c86d92fc9350f8a09c7..d84888f03d92e28995cd4087b511db1ca3c3a4f1 100644 (file)
@@ -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);
index 272a85f32b14c86b040bf854b0df541e463a4af7..f1175142b0a079ef61018e8bff78098ba2829a8f 100644 (file)
@@ -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;
index 8bc95982840fadfcd88952255e75220bea7fd9b1..11d1062a9449f612bf3d6a62c81b26a459427c03 100644 (file)
@@ -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;
index 25011dbe1b96f15b951ba555477f4ba14be94b0f..83ee11eca0e2de4a54220bbc9e2b0d55c6edf057 100644 (file)
@@ -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;
 }
 
index 23fff06875f5703601b1a608937c67f3944422fb..afa99847a5101ffa6399726b57d4189f6c3057f5 100644 (file)
  */
 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 */
index 90c5c2dfd2fd17a515232520daf4dadd1a33d53f..5c8da46614892504c1a30972f3199ffd7309b68a 100644 (file)
@@ -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,
index f2683eb6a3d588a7dff7af9f8830a79dc18206c7..0f5917000aa20687aa1669e5c1e8ed7c1e2edbbd 100644 (file)
@@ -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);
index 662c5f7eb0c54af4cb3c788959109a7693798629..21619bb5b869282a2d0a2f20090d93ea35908282 100644 (file)
@@ -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)
index 9756099a883aa56416bb709d607131ad934a2999..76513dd780c7c0ad01a5f3b53311a2322af4ec05 100644 (file)
@@ -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",
        },
index c0e1b1eb87a9d5ffa4b37bea76359472e2122075..c2c0a5bb0b214c92d90f423c27bb394f66d5da9e 100644 (file)
@@ -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)
index f2a221e7b968263014a85f897872be6eeaaa19c6..3a2b45601ec29d69f07ec4dab98425ebb09add15 100644 (file)
@@ -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);
index 9ded21e79db5866602706ca568dea6613bc0a727..f898c6363729b2a41be58c824f3f3bb145a95897 100644 (file)
@@ -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);
index 0a6876841c20b62ab75f49e41b33ca6c45afbf12..a4e4bee35710fa3f71b1b597c98782765603c45f 100644 (file)
@@ -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---
index da6d1d3b2969939758b6165c67ce3278a1e3e831..80a2ee41fd61726dc43b70724d20e6c63c9b8cac 100644 (file)
@@ -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
index 086fa321677a0b45c3e3a7471fa631c47768327a..c69f0b72b352dc97bfc047a54a5e0d344ec7476b 100644 (file)
@@ -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))
index bd36e55171737734d23e75309e00b3e6142dd8b2..9b74d1e3ad44a51c950257b6588bf082247a75d4 100644 (file)
@@ -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
 #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 (file)
index 0000000..5b58a4d
--- /dev/null
@@ -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");
index c4643c400d462bfc63ce7b4df6c76558e4e92e50..d9290ea788e02665d169e34b4fd7704a116622b4 100644 (file)
@@ -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);
index c8e5e91d7cb571f350eef5ff2b0e26cf317d6460..073b47ff8eee3065b2bf9f1319fc7207c93c2aa8 100644 (file)
@@ -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];
index dd151d53d506dc1e68c3f65b6a9973a51d6e083f..b8fe808b7957c735e0f4c8248ad3bcff14b46716 100644 (file)
@@ -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---
index 1a8eef2c3d58aa9cee7d06cd96a3850dd3ace2f4..633c709b9d996943c415cd0ad49e628a200eec34 100644 (file)
@@ -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;
 
index e463d10368294a57ceaeb17aa3ba27f21dad0bca..ed0feb3cc6fac83436a862b11e49d1fdbc07648c 100644 (file)
@@ -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,
 };
index bad4fa6815c597133d7971f2555f9f141b83a712..eb56174469a7f9d90f96f8f8dc2858b0b0c4addb 100644 (file)
@@ -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---
index bb9670f29b59795a2972effb1884fc20027b1059..27aaaf99e73e62ed9949e6b76838b78b682ac5d2 100644 (file)
@@ -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,
index 203ff9dccadb03206a20f96ea1e71437a98be3be..70dba5d01ad3cc8178318f9976a5922894a86859 100644 (file)
@@ -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;
 
index 8322c54972f3668710c8418c8cf02fb0526cabfe..78c6fb4b11437e2b187cb9e93a9e44ba71806692 100644 (file)
@@ -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,
index 5370c884620b1503a6526bb305ee6c7f495b031f..fb3dd4399cf36e24cd4a1fe809333d140c8419f2 100644 (file)
@@ -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);
 
index 5e8845febfb8f40be7cdacaa2b398434a37e8dfe..c0c127913dec6d471d75ae42be7d9e139329b867 100644 (file)
@@ -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,
index e3f57427d5c51cce6b89687aafdd016308483646..ebcdb52ec739a612216195306a5537c0ca209997 100644 (file)
@@ -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,
        },
 };
 
index 7818e6397e913870dcbfab18b5d171af127f99f4..85ec4c2d2645582339eb7ecfa796e9b37fee91ad 100644 (file)
@@ -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)
index 5b65992c2a0ae4882a3196ce73e0c5ed32cfa6f2..549b77500579e823b60d34633555d482dff1c7b6 100644 (file)
@@ -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,
index 49a30d37ae4a93cf2c84f1e733093722f0799405..e49c0eff040b50a95bdacc050f8ff3a83f172a8e 100644 (file)
@@ -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
index f816426e1085812b6524c037992594e4a539c746..c1fdb8be8beeb193a565384470117e048a0db1dc 100644 (file)
@@ -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 = {
index 960905c0822389cee89101671fea646ce5d140a2..7a07ee07906b280f2d849ae0959c604ee58d411b 100644 (file)
@@ -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
 };
 
index 9c77c736f171a8af6773d7d4a3ca4e562115cc04..aa53115bb38b91d45329be5914241591da6776c7 100644 (file)
@@ -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);
index 7219123fa0a433985bd24a6d775d70aea6365529..c0bc41a784ca253b012f327807e9d42a1ff0197b 100644 (file)
@@ -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;
index 689dfcafc6d47ed843f35ffd1a9ab09517f36d43..3789affbc0e5cbff032f5cf225725fd4a80a013d 100644 (file)
@@ -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);
 
index e10ffad525a788e06bae64c8581f47280be9c4fc..60e2b701afe726f05b041f0694ed6b454ddd05bd 100644 (file)
@@ -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;
index 3491d4312fc9252639a082f7897643a2ee6f3c0a..42d4e6ad58a5f81098d7d7829528ecb057434e3d 100644 (file)
@@ -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
 };
index f2958df9a1e41f6e460a6bb51f786897bf01c7a9..98f4522fd17b7e69d3c524568d4b8c991ca80533 100644 (file)
@@ -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)
index f195acfa2df7dc4efcc5368173be475e6cd5b72f..2ea221ed4777f01527a81d08d299dcf44a3b6b8f 100644 (file)
@@ -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,
index 7203b522f234591f6db66e0cd447ac852adb058b..baca0bd1b39361b7d5ce7ff90a82cc43064fce7f 100644 (file)
@@ -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)
index c771de71612a8f75d82dc11e2ca629015c7c78da..34a485363d5b7dcc77b715577bd0cc63af19b5a6 100644 (file)
@@ -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;
index 8baff4e5d964ed6f172f0cd1f44a3ac2c3a5ce0e..0c61fd50d8829f13789b7c3583000929de25084d 100644 (file)
@@ -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;
index 86b6d8e4e6cd594ec39bdb5ca41fe130008fac64..a227ccdcb9b5e94447a5cd3c23c9ebef94b08932 100644 (file)
@@ -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,
index d7a3533d990b165774a585343a440217b90ec517..c2d696c88e4687c46233b017429f2fc86c9aca8f 100644 (file)
@@ -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);
index 855bdafb1a8759dec969cd5c84a212df0ed7daaf..f36bbd6d5085da5f5d2ba830b88c7e517e3f5f9e 100644 (file)
@@ -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);
index e1df4b76c8850bab2d3a4af5f8e08b1a7def77eb..842fe7684904351652f669d7838966597e467bcc 100644 (file)
@@ -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;
index a92ddee7f665c63a33156ac864f8d1e5e804f817..a206779c68cf2d48f5a6bcc6f98b99dd2c98426f 100644 (file)
@@ -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,
index d19f82f7597a6c3e079a71dffc727cd5fbd9cd21..56d3f697e0c7f0a05d8044a37f954c8d536f1c0a 100644 (file)
@@ -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,
index e213da29e73d4debb9666810c2482cd1f8f51b50..e4466a36d1063b38c71b3937ba5cc055482ab82a 100644 (file)
@@ -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,
index b5086f1e637f8179311e29c150fc9f1301b93bdb..fa314282c9ad332673e007c199981b04edef0ca0 100644 (file)
@@ -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;
 
index 7bae2ad7a7c0ed66b360c844960bb3b4ed50c683..71b3d7daa21d06c70e4b62732c91b04137342c64 100644 (file)
@@ -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,
 };
index 623dd8635c46eb0fd9e209025ff60464627dbcd6..aab83a2d4e0770a2cb781c5e6062bdb42360e413 100644 (file)
@@ -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;
index 4bd416b72e65a9a5423930e9a52340bb087f2174..f55267363f355d1238dfecf9eb8df1367f53aad1 100644 (file)
@@ -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.
 
index 9786c0e9890edc5548410741c07a82bcd34c1ded..219f6226fcb139a50795da6af0f4daa5a8ceb12a 100644 (file)
@@ -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,
 };
index c7ca7ec065eeea7dfe164f96384ec3aaf464809d..39387d67b7222beee3a5fd122218c645851f90c6 100644 (file)
@@ -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,
index d4310700c7a71409ae399bae819bac5fdebe32fa..a1adfaf87f499bc84a77dbc714abf8eba3adb4ef 100644 (file)
@@ -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,
index af6451dec2954aedce75ef45cd9f26b9edd88b94..172efbecfea2b502c26cf8043770575b229743d4 100644 (file)
@@ -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
index 72897c47b8c849c31cf387c6cd63f42d624be07c..e8d4db10c8f318dacac488af5f41510c7f3c68dc 100644 (file)
 
 #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 */
index 4833b6a9031ceef2e9cfa57390ff52e719eb5ac9..a2998bea5d4b42690ca1334322d5ebe396ef0805 100644 (file)
@@ -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);
index 9c5ea6c5b4c7597059644c57d27f2943cb65b792..0991534f61da18b276fd3d602259371cba84f87a 100644 (file)
@@ -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,8 +290,25 @@ 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.
  *
@@ -302,6 +316,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.
  *
@@ -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.
@@ -423,6 +444,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.
  *
@@ -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;
 }
 
index 2245c3895409d149c402fa70bdff529790046e28..10bc093d2ca43d9c0dd9ae309734279ccf1661bb 100644 (file)
@@ -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;
index 6e5bdd1a31d92c499c43fa40bc11a95bf7034bb7..277f17e3c8f850bac954db7d99c55b7f06d194eb 100644 (file)
@@ -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);
 }
 
index 620fe939ecfd357ed1e852bd0350c3687886a8b5..60a83ad103700602814842e8d3f47e40386801e8 100644 (file)
        (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))
index 18704929e6422ec15f0c59ec8c4abcee8802e532..3369a50ac6b4fbe087860883c9dd9afc951c3238 100644 (file)
@@ -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;
 };
 
 
index fe66d902dc6224b8199dbd856ef0eebf9f2dde3b..d755acfe7a4076d71a5f03d6fcdd491c12d53cba 100644 (file)
@@ -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 */
index f6cfdc6cf20ffd88f6f4472452f27f97067afe60..09096b43a6e9f7da5a9304093da121fe2e7aeb12 100644 (file)
 #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,
index 9165b89a4b1923d6948bcefba018f2d6cc707633..ee6e7ec854577b8687bb1e8688ed7e83261664cc 100644 (file)
@@ -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;
 };
 
 
index 01611b33a93de82c8b735b2e1c3e115a9b8e807f..940ef859dc6054338b884abce2c519e0ba4a89ea 100644 (file)
@@ -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 */
 
index 1b1999d34c7180f41649b606695ecccfbcb237c5..bc2f65b32649de1dcbd5b456a4b915fdea9d1ef3 100644 (file)
 #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
  * 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 */
 #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
 #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)
 #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. */
 #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
 #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
 #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
index 614981c02264bcc957d7dd99f629768492746e6b..09b625e0fdaa999260daaca271adac8b67112108 100644 (file)
@@ -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 */
index acf2fe4ca60851091c39c2e8ed8ec6fb71aa2d78..adbd91b1bdfc56a6edc93c3409f798e27de1d84c 100644 (file)
@@ -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;
index 348ed02d3c69928c3991d7c8de046ccf95c0a3c9..89ec0667140a02dc67f16b2ae79a59eaeaccff5e 100644 (file)
@@ -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);
        }
 }
 
index 24b8e505b60c941e8b75f2e45efa3201347c7e1c..b4d7b26c7fe78906be5998608c3b0d46b7e1df84 100644 (file)
@@ -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 {
index cc8434fd606e2a089e20708f4ee12794fdfdd1e1..df8c30d1a52cc4d1fc35e6fb8f7cf6c1b73d31c3 100644 (file)
 #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"
 #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;
 
index 148604c3fa0c79c51bf0fd1dc75edc3f7598c670..62c670619ae6600a631bad3a351ceb1abec08e5f 100644 (file)
 #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) ==          \
index 865095aad1f6494d985f4dbe15ab1ae198e7e74f..2a35436f90956744a2efa443062001a4acde1727 100644 (file)
@@ -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
index 49e7a258da8aa91554410900a4d23036e13e85c5..3a1c8a3cf7c91af5ada39f9ded17e604212b2c01 100644 (file)
@@ -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;
index a8800ac10df970b280690272f8618247f80d0823..78ea90c40e1902af09272a80b09010da52ae6c6b 100644 (file)
@@ -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,
 };
index d9308c32102e998fb22c45f9ee5c21482286072a..d330e81f5793ad47e8f6257d3e08c728719c9651 100644 (file)
 #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
 #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 */
 #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
 #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 */
 #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
 #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
 #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) */
index 959c58ef972abffa33ce9c24638bffbbc366e720..3227fdde521b09323f6e4ba58188198052aeb70e 100644 (file)
@@ -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);
 }
 
index eef6e1f8aecc1eb5540c4d32575ef76950a67c47..7d10e335c27d22e52a468faa50188448492fc69e 100644 (file)
@@ -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 */
index ede532b4e9dbfd945d0372733a6131721de8afab..25dae757e9c42661b094270786d5f141ab72c3b4 100644 (file)
@@ -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))
 
index b8c4e21fbf4c28a89e74832b32bb9065bf8e07c5..af3f7bb0b3b8302854f4eebff78519af1a3a40bb 100644 (file)
@@ -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 */
index 71144b396e02b7553adedc1227f9fb2e71145da7..ea6f4a036401aae98d9e02126119d343f05ede71 100644 (file)
@@ -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)
index d3eb8bddfb2a45a78c5be13955eab69baed10438..dc50f7836b6d72f7de40de17a6a4d77dfcb273eb 100644 (file)
@@ -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;
index ce1eac529470de89cdbc2107a649affbfedb3761..7cce42dc2f20e2d4ce014380a48f583083899e1d 100644 (file)
@@ -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
@@ -782,16 +920,6 @@ bnad_cb_tcb_destroy(struct bnad *bnad, struct bna_tcb *tcb)
        tcb->priv = NULL;
 }
 
-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)
 {
@@ -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
index d78339224751a55e01f1456397f65701dd909f93..c1d0bc059bfd57b1d6ac744a7ba5c6ccdf1945ae 100644 (file)
@@ -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 */
 
index 40e1e84f498473f6a0c53b433acddfae1e4a012b..455b5a2e59d496b64d8c90f327dc4539e7ade67c 100644 (file)
@@ -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",
index 32e8f178ab76a964af67dcce189e8ec84195ab42..14ca9317c9150139f3047ab29fb7fba7835bdb61 100644 (file)
@@ -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)
index db931916da08c8ddfd26b9068a94b7dddd1bfb46..ceb0de0cf62c6e4f2dffcc0c650f256dd8adbbf1 100644 (file)
@@ -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
index 35fc6edbacf807ce098b452ede6bb43b2ee77dc6..3becdb2deb46c8dbfb3faa4e2916e1cdf41bc6d3 100644 (file)
@@ -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>
 #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 (file)
index 0ef6328..0000000
+++ /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
index 033064b7b576ad9199702d0a515331dda141fe41..a9b0830fb39d90b3227fe14741c8a4a3f09dc2d6 100644 (file)
 #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>
 #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");
index 335e288f53140159e2f1956a716713b69c03933a..570908b935784204e6b85d7f44a81c5a499db409 100644 (file)
 #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
 #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
 #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
 #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
 #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
 #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
 /* 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
 
                __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;
index 16814b34d4b66ae8a39414a14e2bec0a72f89029..b407043ce9b0df3c1286fb3c0051f012cfa5e5b0 100644 (file)
 #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 */
 #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);
        }
 
index 2de50f95798f266213b9c9a150145929f509fc16..d40c994a4f6a2c807965e44eaf81f2be0053fb50 100644 (file)
@@ -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
index 1d17c92f2dda175547ec107a599fa8f42b37ce5d..c8fdeaae56c0a70bbb28e147979738f5533e2fdb 100644 (file)
@@ -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)
index 47a84359d4e44b65fa6536553215f714a2df47a5..d84872e8817131233c9f949615ec9b0492d1ebe8 100644 (file)
@@ -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;
index 8a43c7e1970190fcc95daf581e4f1cee9363f55e..e0a03a31e7c487489006aa57594d86cfb73e27b0 100644 (file)
@@ -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;
 
index 8bed4a59e65f2a51a071c98cd94b7eb6e046a6e9..b146acabf982005db2ed2128540f8d99810f3d87 100644 (file)
@@ -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);
 
index df01b63432415800e418b2df97e8462c85cbcfb8..8c82248ce41624156b2e429b6b716fae013e00bc 100644 (file)
 #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.
index 9c9f3260344a346175c149824c249cd3ebf72be1..f15ee326d5c19414563b30abbb66ba780fd59b00 100644 (file)
@@ -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,
 };
 
index 2dbbcbb450d30470b76e024835bdc00916af0d54..942dace361d229e061545c51340f9fb37d194dd7 100644 (file)
@@ -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;
 
index aef45d3113bac5e9200d4dae8efc9a754a38d18e..3dee68612c9e87868e3b5b61b475693273480319 100644 (file)
@@ -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;
 
index 0df1284df497d8247fbf602d6578381099619d06..130dd9d5b493d6600a0e68194a1a4919a414151b 100644 (file)
@@ -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,
 };
 
index 730ae2cfa49e34ee5d361d73ac437ff715d4e50d..45f2bea2e929b098ce2fa90be9987406c66c8d05 100644 (file)
@@ -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;
index 9dad56101e23fbcca6a0360c2d223ae531d4afb3..0188df705719d8d601c6d4dd4685f1f762c023f6 100644 (file)
@@ -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,
 };
 
 /*
index a65c80aed1f2a214d99e520a2125755e2c16ecec..283f9d0d37fd4e4b689e698f965036ba6cda40e2 100644 (file)
@@ -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 *);
index fe3fd3dad6f712a91c5af9b314f6bad8a44a36a7..7127c7b9efdeb59474554b70c71b52754a26bc24 100644 (file)
@@ -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;
index 94606f7ee13ae2e969c9c91fccce118d908f6b02..1c7b884e337147a32e588b83750e4ce767f87d4f 100644 (file)
@@ -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
index 9cc706a6cffdfefd8b967fae3da9e0d052802a15..b63f8d8a42612940d7cd403493327b0b7d98ff2d 100644 (file)
@@ -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.
index ad1468b3ab914442575f3fce1e35754da3221789..64866ff1aea0d9894f2a296ebed80324e5638f15 100644 (file)
@@ -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)
index 36499d5edd95b002e8fa59e91512f322ef1f4fca..c73472c369cd6e7334e42baf3d61f15952ece55a 100644 (file)
@@ -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
index 17ae8c61968017aa6aa6a7477ac062f8dba79669..9f992b95eddc1b13209082890f13d1d9a8248964 100644 (file)
@@ -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)");
 
index 77335853ac364bcedbadcec6449ddac45b71359b..eaab73cf27caffbbabb2904c47be6fc7941f5303 100644 (file)
@@ -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,
index f879e922484685aa8523dff90dcec75703631758..4c830030fb06ca23056f67a6aebe815a79d57841 100644 (file)
 
 #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
index d23755ea9bc79c68b793af65c824dfd6477ddb78..83139307861cd720edfd78d71d7abbe6b2265ff5 100644 (file)
@@ -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
 };
index 44f7e8e82d85dbbdc9b67031b708e41bb9e8cb9e..df5a892fb49cb52a5b3623bf44cf4fc3ab261828 100644 (file)
@@ -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;
index ae937c6749e7847facb80b06553c356dd32c627d..93a4afaa09f125ca92ec6f2de037de82215db8c3 100644 (file)
@@ -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;
index 885700a199785a6b840b5cf4bddb9494d8f5bc67..1e9443d9fb5732fffa352683de3a019679c7f6b8 100644 (file)
@@ -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,
index 75d45f8a37dc170db51678919acbc27cc9cd2ac5..93845afe1cea105f21751c4bea54100405799b42 100644 (file)
@@ -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,
 };
index 7c1ec4d7920bf607e43cd50c5c5624adcc86b08b..c7b04ecf5b497ea26f969ce52eeaffccfc0ee5ef 100644 (file)
@@ -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,
index 138bf83bc98e346c66b2c90ff691512e49f539a8..88feced9a6293432e3dd5316a8ec48ab284ca3e7 100644 (file)
@@ -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);
index a059f0c27e28f19251a282b36f35b1254e90b273..1d342d37915cd1d45b8c00088079e6aef2b273fc 100644 (file)
@@ -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:
index 3b83588e51f6ad41ac112b06d9f219c33eb957d2..28fc11b2f1ea9235ce8c9fdb3ac8abbb35b72bac 100644 (file)
@@ -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,
index 290b26f868c9f7d358c125822dd67bc412d85b16..2c177b329c8bd4ccd1bad6ffef72deab6b3dc8a1 100644 (file)
@@ -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",
        },
index 7a28a643394414a40eb3d3493eb7ffcea188f7cc..1b8d638c6cb18963f7d06dc57a5355bc8e93272a 100644 (file)
@@ -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
index 804db04a2bd0431d970b39bd8e7381507d78d799..231129dd1764e70e1c0b8d9c7195685859d2ea42 100644 (file)
@@ -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.
index cf4c05bdf5fe71262abf8fd4ac10e11e0cb0240a..abf26c7c1d1911c2f46a5684dc102f4181eba843 100644 (file)
@@ -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);
index af60bb26e33023ac523b672f76e68dcbdd172f92..f2875aa4766170a100b7a21aeffac60e1b9c8d57 100644 (file)
 #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)
 {
index 0936e21e3cff3d6cdf3767dbf1d0e708744f9b26..d6552e19ffee386c369a13ae651634e9da2e1b62 100644 (file)
@@ -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);
index 8e6fb0ba6aa9631132686566859a8228c0c1fb86..00454a10f88d6111f5bfb30987703c04d807e8ba 100644 (file)
@@ -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,
index b755f7061dce56edf88e486662c7d0c0b100a2a8..541d4530d5bfadb2d038b3aa4e233a069cf9c94a 100644 (file)
 
 #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
 #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
index d1b6cc5876393cc598a5d473fab158bb13477bdd..f95612b907aea3a8341752f3e02f3446b432007e 100644 (file)
@@ -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;
 }
 
index deecc44b36177aff72f65f1a258d5b7391827a6e..55d32aa0a093afa74de8c26661468a97b31d5cc7 100644 (file)
@@ -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;
index 94b7bfcdb24e4a2fb3d9639a9f053c6186bfef87..8db1c06008de16107ba5475580a696f04a5d745a 100644 (file)
@@ -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  = {
index 0e4a0ac86aa8f1a9ad2d760cb066974abd678c79..c706b7a9397ed6f13dedfee142f99ae50a98ff98 100644 (file)
@@ -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)
index feff51664dcf76974cc62a58be978bbbe83f0cf7..5ba6e1cbd346723f069074016ce06b2bb82a223c 100644 (file)
@@ -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
index 3d1839afff6574ac96a9f4f2c7955739a8574567..d4d19b3d00aed69b8d905307f16b53e717926dcc 100644 (file)
@@ -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
index fffd20528b5da8e0864eeddcccbf4f034a9ba9d2..0704bcab178ab64a036e6cec7e44167622c7271c 100644 (file)
@@ -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);
index 8408c627b1953a230c1f25d24b05217b0718d19f..c5a3bc1475c7f58381b3ad654501a5a116821651 100644 (file)
 #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 */
index 2933d08b036edc437b0e026ed55404fa34c8b4fb..817d081d2cd8e8b9d2fdddfc4a69edb3dc6d7b32 100644 (file)
@@ -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 (file)
index 0000000..c40526c
--- /dev/null
@@ -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);
+       }
+}
index 2b7633f766d98a0d79138fc317303579c71ddae6..e9879c5af7ba05dcea3364fb3db9c13d028998eb 100644 (file)
@@ -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;
index 151453309401694360f311ccb09e0caea8480b01..2bafbd37c247ab52802e64b531ac2e7ccc5e148a 100644 (file)
@@ -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;
index cdf702a594858146fd4f04ab02966d941edeeea5..18e8ef203736bf2154967599a102fd454e7cc05a 100644 (file)
@@ -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;
index 19ac096cb07b702fd988d53a224d03119c674e59..bffb2edd68584633aa8b5248fc27faf0990a05d5 100644 (file)
@@ -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.
index 1afb5ea2a984e2bc91aad9983bd14a0a32ae1e15..418068b941b1cadea61271ba5cc52aff01aefc10 100644 (file)
@@ -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);
 
index 3f4391bede815f4b2f97d0557d4af4d5848f57c8..e3c7c697fc45c2e1c5670cdc6a04b6d93083a40c 100644 (file)
@@ -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
 
index 067db3f13e918ddc7ac896ab0212e20921fd8d31..5d353c66006829ef08a3ffdef537c825d367f58b 100644 (file)
@@ -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",
index 6eba352c52e0809127d7e02ffea24e413ca82a47..f42f1b707733269bdef7dde20b7956d8cc74a54f 100644 (file)
@@ -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);
index 3efbd8dbb63dd27b268167b9ad9538a455ef86c8..f045ea4dc5144e60be6fd25b730e8fabc65f2871 100644 (file)
@@ -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);
index 6b2a888174732e613ec5094153fd68f29505d749..4ceae9a30274baf86f57482274625abfd75ce9ef 100644 (file)
@@ -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);
index b9773d2291927e4164197b20ca78a00694c6528d..6529d31595a7e595f4ebd9e55929d017253c2c17 100644 (file)
@@ -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.
 
index f4d2da0db1b149938e7c9d0e9905dfaa7db2849f..19b64de7124b9ae51e0649b887bc1b208c7627b3 100644 (file)
@@ -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;
index a0fe6e3fce61a5ad7b4b17b7de723e0798ab9086..256bdb8e19948390eeb4e73513b475e377350849 100644 (file)
@@ -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);
 
index 479e43e2f1ef842cee474af85625cebd8ed30606..50ea12bfb579ebe47fd2d58ed082810e6e513cfa 100644 (file)
@@ -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);
 
index d3123282e18ec3b8de290899bd6117df14995fa3..39251765b55d444c8dbc0ab0e380e89546d4a964 100644 (file)
@@ -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);
 
index 872912ef518d163f6a4df7108e53fad0bb658afc..795f1393e2b6d006fd568e91d22bfd58dc7d08d4 100644 (file)
@@ -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);
 
index 415e9b4d54086ce6e7e8a2afdeeb2ea1582a2f10..f91202f42125d3088c6fbb69ac9c87b3417dfb07 100644 (file)
@@ -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);
 
index b68d28a130e664e2042bbb9a4335710964f861a7..f2fdbb79837eafcc7baf00d070efb48251bd1f7a 100644 (file)
@@ -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"},
        { "", "" }
 };
index 1b563bb959c27d10a14d0cb0f3881c0f5a0962b5..068d78151658819ba5a88895df55942d59134e83 100644 (file)
@@ -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)
index 0cafe4fe9406125af6375cd8859b1919ab0d62d4..ddee4060948a3688d884b3591bdc7aee4d992992 100644 (file)
@@ -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
index 29ce9bd27f94ea21490f5b6c626d5a709a05ccd9..a59f0779e1c3a00a2603c54eb21343cd962945b5 100644 (file)
@@ -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,
index 9089d00f14216431b9bf33db13a51b35414184b9..14e30515f6aa86a9f45d88aded9a027c736872b4 100644 (file)
@@ -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)
index 3d6839528761c77462f0fee647d8fab1984913ef..8fedd2451538c255d0238a7f367bbb2d402aa2c8 100644 (file)
@@ -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;
 }
index 222bfaff4622959df30eb7b89f25a2f7764dcc32..294da56b824c3d0c4259b76f01858c80914fccbf 100644 (file)
@@ -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);
index 1301eba8b57adca90d79ce68ca75d7c81ec05494..750fc0194f3731d52de240aae5d29b7a4ac0f220 100644 (file)
@@ -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;
index 4dd18a1f45d27b7fd95ba6d486f509a7bce24a4d..e73c2c35599375a45bc253783df6cdfd2b91385d 100644 (file)
@@ -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.
         */
index c98586408005a0dbbb557e4ae22fc3f49ba04a48..c77d010d5c5992da6c25761f6d1e1747f12d3273 100644 (file)
@@ -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.
                 */
index 76edbc1be33b4d1151e72c24c1f621c830c3a039..02a12b69555f6fb5d71fe2089992f5fad5e354cc 100644 (file)
 #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) |
 #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.
  */
 
 #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
 /* 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
 #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
  */
 #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 */
 
 #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
 #define PHY_REG(page, reg) (((page) << PHY_PAGE_SHIFT) | \
                            ((reg) & MAX_PHY_REG_ADDRESS))
 
-/*
- * Bits...
+/* Bits...
  * 15-5: page
  * 4-0: register offset
  */
index 04668b47a1df1a65f98eef94bea619d7a0c0c71d..6782a2eea1bcbfb893681b8d26428d8b0410981b 100644 (file)
@@ -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,
index c11ac2756667bbf7205be4b5d1c903b00e7c3e4b..f95bc6ee1c227c89a2e158fde491dc03ef173b4b 100644 (file)
@@ -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);
index d37bfd96c987277980d4ec7b2e2db85f7e1dcf36..cf217777586c246561120c0877516f22d3ff6b89 100644 (file)
@@ -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
index e3a7b07df6294781559a72537d7949b711e82d00..976336547607e31caef68c8eaf528ddac78682da 100644 (file)
@@ -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.
                         */
index a13439928488c7aeab640d0a99f0833a5e74f203..54d9dafaf126609f4e9796b80f8d92de2c966745 100644 (file)
@@ -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;
index bacc950fc684ee35c1d2ad0003098f4b890b9685..6dc47beb3adce59a46116bc37bc5e14ec931e109 100644 (file)
@@ -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++) {
index f444eb0b76d8d9c0c7147b8dc4a9fa7266d517b9..fbf75fdca99422743f35d3d9a114fcdef235563f 100644 (file)
@@ -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,
index a969f1af1b4ee22f3fb2ff0693c54498232df3fb..b6468804cb2e74e8e317622ae4f36067c8f8780e 100644 (file)
@@ -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
         */
index dfbfa7fd98c36f6ccacd82cfe9b083f2a7ab4baf..89d536dd7ff51e3cbcd688f682cd00a84e000ce7 100644 (file)
 
 #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
index fc62a3f3a5bec8b3e7ce0fba893ae50add89f22a..28b38ff37e843a028f89d7fab86827a777e5a098 100644 (file)
@@ -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) &&
index 97c197fd4a8e5215fa5dea76d4785cd5d765a6d1..624476cfa727cc32efc39a8846fb3720742077ed 100644 (file)
@@ -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
index ca4641e2f74870c1bac8c147ad231b19ba660e12..fdaaf2709d0ae660480e3c6525e116481a369c4c 100644 (file)
@@ -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 |
index e85c453f5428cf31723373468d51f64099e10fca..44b76b3b6816692f2bcea6682950791a92164bda 100644 (file)
@@ -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 */
index de4b41ec3c402da0829357edc5f77c1821369a5e..45dce06eff264d77dd5d6b350ef2e3a1dd94447f 100644 (file)
 #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) */
 /* 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 */
 /* 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
 #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 */
 #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
index 77a5f939bc7413ed84c5dfb7e2aa97a166047743..fbcdbebb0b5fce2c4108a130e24d490cbada6cf7 100644 (file)
 #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
@@ -67,6 +98,23 @@ void igb_release_nvm_i210(struct e1000_hw *hw)
        igb_release_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
 }
 
+/**
+ *  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
@@ -137,60 +185,6 @@ void igb_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
        igb_put_hw_semaphore_i210(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_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
@@ -228,49 +222,6 @@ s32 igb_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words,
        return status;
 }
 
-/**
- *  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
@@ -328,6 +279,50 @@ out:
        return ret_val;
 }
 
+/**
+ *  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
@@ -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;
@@ -422,6 +441,100 @@ s32 igb_read_invm_i211(struct e1000_hw *hw, u16 address, u16 *data)
        return status;
 }
 
+/**
+ *  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
@@ -518,6 +631,28 @@ out:
        return ret_val;
 }
 
+/**
+ *  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
@@ -547,28 +682,6 @@ out:
        return ret_val;
 }
 
-/**
- *  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
index 5dc2bd3f50bc1df3076d59e61ba1f30209bacc5b..1c89358a99ab84b384f4d6819dd550aa7cc2a34d 100644 (file)
@@ -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
index 819c145ac762229df4330ea1d79110133e43e0e9..101e6e4da97fb5287852d555409618c7cf7bf854 100644 (file)
@@ -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;
index cbddc4e51e30d9c304b11c75250d04ddde39c5b7..e2b2c4b9c951fd704a5d452f00e6efd190ec307b 100644 (file)
@@ -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
index aa5fcdf3f357f033947857716d1f102310ebacab..fbb7604db364f59729bb3f6c36d41758d4cf40ba 100644 (file)
@@ -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;
+}
index 825b0228cac0ac5c17dcd9a903240b9a17d95e6b..7012d458c6f7eff8df5ae1c0e25cd4a5abaa486d 100644 (file)
@@ -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
index 3404bc79f4cadf76382c5dbfca62b4d4ebe1f693..fe76004aca4e7a8464811629d9cfec18dac2f8b2 100644 (file)
@@ -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,
index 6ac3299bfcb9fefe23845b294a72e2119563ec36..ed282f877d9a0b08df7b7a2673d0e3d0d67c5216 100644 (file)
@@ -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 */
index 8aad230c0592e03f5f3b753f636f0a38dd35d4a3..17f1686ee411fe3e63aea5fdcfacaa1abe6e8ee1 100644 (file)
 #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)
 {
index 2ea012849825224af910ba7189aa850b58610806..bfe9208c4b1879db6a52695328d1640a7f3e2064 100644 (file)
@@ -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,
 };
index e1ceb37ef12e406fd7ff6dff13b08c18548fcea6..31cfe2ec75dfb32b7da36311214c0ac2606015f4 100644 (file)
@@ -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;
 }
 
@@ -959,6 +892,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);
-
-#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_VLAN,
+                                (E1000_ADVTXD_DCMD_VLE));
 
        /* set segmentation bits for TSO */
-       if (tx_flags & IGB_TX_FLAGS_TSO)
-               cmd_type |= cpu_to_le32(E1000_ADVTXD_DCMD_TSE);
+       cmd_type |= IGB_SET_FLAG(tx_flags, IGB_TX_FLAGS_TSO,
+                                (E1000_ADVTXD_DCMD_TSE));
+
+       /* set timestamp bit if present */
+       cmd_type |= IGB_SET_FLAG(tx_flags, IGB_TX_FLAGS_TSTAMP,
+                                (E1000_ADVTXD_MAC_TSTAMP));
+
+       /* 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;
        }
index ee21445157a3e8907a7b01267806d10b3ffab6e2..ab3429729bde4134a0310a6199cf9eb1737369b6 100644 (file)
@@ -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)) {
index 3e18045d8f89f69d5e374d246f49a91320399a0c..d9fa999b16856e41f79a750c92d94223dfaa6d98 100644 (file)
@@ -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
index a895e2f7b34d99b4afa870cfaab801b1061ab9db..fdca7b6727764fb574ffc88a85f47ee81fdc5f23 100644 (file)
@@ -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)     \
index 0ac11f527a84e289d8d42f693c7ebeff67e198a7..277f5dfe3d900dede1ff0cc83a061a2cc92a6ed4 100644 (file)
@@ -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,
index d99a2d51b9482bb54926b3bb249ef13a26701201..ae96c10251be9c0ac64c7ca25a72993ae7eae22c 100644 (file)
@@ -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;
index 07d83ab46e2118ea3f5164a2482e9204bab27ef7..04a60640dddaaaf4f01d85169d61d3e77a3d83e8 100644 (file)
@@ -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;
index 89f40e51fc134f0537fe8cf6f9f9c3efca44f94e..f3a632bf8d96f8bd76983e8990c80f1cefe984ac 100644 (file)
@@ -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
index 30efc9f0f47a3cea7cf5aee5438b5ad70c208f30..8e786764c60ea186084a7c5b18e9641abeef2a0e 100644 (file)
 #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_ */
index 1077cb2b38db15f4123eca7d9d71492df86b0a05..1073aea5da4056ec1a82686338d24c71d2dd99e2 100644 (file)
@@ -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,
index dbf37e4a45fda722df461cc11eaaf8b2bd0449f8..5e68afdd502ab586c31bf074aac9dd9180475d2a 100644 (file)
@@ -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,
@@ -1761,30 +1782,6 @@ s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw)
        return status;
 }
 
-/**
- *  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
@@ -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;
 }
 
 /**
index d813d1188c3617156e6e35ed260aaf1ec3ab2482..f7a0970a251cfe1835c5792401a9f0ed3547d118 100644 (file)
@@ -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
index 8d3a218890993cb39887b904848403a3f4d547f7..50aa546b8c7a589100be6bd88eac590adf314d98 100644 (file)
@@ -36,20 +36,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
@@ -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,27 +133,13 @@ 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,
 };
 
 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
@@ -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,
 };
index 116f0e901bee2305324c4fa9035d19e6c5676b37..32685842434565e609a5f8589b67497609074aa4 100644 (file)
@@ -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;
index ae73ef14fdf341795cf499c5abab207704a70d34..252850d9a3e0925b45bcb3524dd7c6e490540616 100644 (file)
@@ -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);
 
index 17ecbcedd5481d0dcafa46138839088478cbf2c6..8c74f739011dd6a09ddbae19b4cf3bbe663c8a43 100644 (file)
@@ -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;
index fa3d552e1f4a1e6b0cad19c4e4d5610551866638..20a5af6d87d0e8747027964ba01a03bd7e3ca24c 100644 (file)
@@ -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,
index 310bdd9610757558827d31155ad1bc839d617bfb..42dd65e6ac978906b70bd565c1811a26fda3bb3f 100644 (file)
 /* 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
index d9291316ee9f3aee8bbe54710a6ebcffb37c6ef7..1a751c9d09c47f319e45d76a9c2bbad8573016d3 100644 (file)
@@ -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,57 +740,19 @@ 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
@@ -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);
index dce48bf64d9616beacb3ea9b081b6d7aea0730c2..85cddac673ef41716d9a34f027b1bcbb0cfb903d 100644 (file)
@@ -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)
index 0722f33680926e9c8e79a0592708cfc0c42806e2..9cd8a13711d321546f4ff7107714dfde2fbf490c 100644 (file)
@@ -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
index de4da5219b71f652363e2d5a6ded7c639e4ff4e4..c73b92993391b5db31d7868481e65b4b1150b403 100644 (file)
@@ -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);
 
index da17ccf5c09db9b8647a724c55d9c98eae4fa94f..3147795bd135b57137105a3b4769d0f34a7c6faf 100644 (file)
 #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;
index 4a9c9c285685294df5b5531c689f0e11171056be..fc0af9a3bb35b354e26568af3b68d54c9a3c5018 100644 (file)
@@ -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;
index de1ad506665d6a33c223c8a73fbada54f39df832..257357ae66c365169d6130306d9180789965c98e 100644 (file)
@@ -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,
index 946ce86f337f702701f10133faa8c71b099d81c3..0bc30058ff82010c81bcc7c15906f2d962e0f4a8 100644 (file)
@@ -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 */
index 0c7447e6fcc84a3a42044b11d0f85fbe3f2d0904..0c94557b53df9b656dafd2e1a96f56c3803c8288 100644 (file)
@@ -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,
index 47f11a584d8c04f9f4deaeecc643729362ea6917..7b1f502d171606366c06c767a65eb7ead6add2aa 100644 (file)
@@ -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__ */
 
index 60ac46f4ac085380630c5f35af7892e65cc980f5..0519afa413d22714b88e355f1cea862f11650cba 100644 (file)
@@ -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,
 };
index 003c5bc7189f7ef0138a46f96f10f64b52154d5c..c124e67a1a1ca72599d8fe81f449f32f69480f4f 100644 (file)
@@ -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,
index 59489722e898aa1e517959855c7c7561f858ba65..10d678d3dd018bf40d4ca857459de4c81cd438d6 100644 (file)
@@ -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;
index d19a143aa5a8690db119630228f40bd896d1f84f..5544a1fe2f948f5e64ab2c38e00df0aa82255efa 100644 (file)
@@ -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,
 };
index 78946feab4a2de4c187138d02c01418cf8b4fb6f..3269eb38cc576924a958354b9e664b1a92b26dd2 100644 (file)
@@ -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,
 };
index d8099a7903d3d7bd2fbb5fd627bf822016cc09f4..bcdbc14aeff0d40b4514b777fd7b4d27541cfc9f 100644 (file)
@@ -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
index 5f027f95cc8422fe6887cf41b42c2572b6f809e9..eb520ab640143b918615ceae86a8f5de36bd23b7 100644 (file)
@@ -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.
index 9d0b88eea02bfcc549d259a0a4ca6ff06ebe4308..03447dad07e959082353ecd1408754736a61e2eb 100644 (file)
 #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,
 };
 
 
index a52922ed85c12e06a07caab7e4ea8977b53d8135..3a2b8c65642dd7566ffbccfbbcc0f479ee3d49f2 100644 (file)
@@ -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/
index edd9cb8d3e1d8f09cc1715ddee967b5fa58181fd..7d1287f81a31037ef3bc1bd9802500ca3ffcc629 100644 (file)
 #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;
index 5aba5ecdf1e28157fadf44072c87a4a98511d249..f76c9671f3628c22bbb1280316b8f4eb57c71c3e 100644 (file)
@@ -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:
index b35094c590ba94206be751643a7ad3a17cab9b7f..1f571d009155de6f96335179a744f5c695b8e20e 100644 (file)
@@ -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)
index b84a88bc44dc2a5e7391ca7bc7116344dd63a97f..c48cf6f6529c2c28bdfde6b302432d3c746c6e50 100644 (file)
@@ -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) {
index 2aa80afd98d20038b2a174ac38a52a5eb003eaba..200cc0ec805226506623a90e501f0db527a1dd41 100644 (file)
@@ -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,
 };
 
index 9d27e42264e2b64aea3827d760c409ab3de0c301..334ec483480ba657da74487a03c15c2f011f1257 100644 (file)
@@ -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);
index dccae1d1743a6241679d2ece28528736404b59e6..07a6ebc47c929bdf6aabdfedf23fd20901226921 100644 (file)
@@ -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,
 };
index 24fb049ac2f28fd7f3c71559fdb3f96559eba495..b71eb39ab4483e6d6bd7021d42bdf620f0977a9d 100644 (file)
@@ -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);
index 1540ebeb86695903ac81d458bd2450436385bd49..286816a4e7833c27e2e994a400be44f968c4c354 100644 (file)
@@ -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,
 };
index 38529edfe350842abf6e9613de00c9fe4b1b534f..ef8f9f92e5476daf73be7e7e3bbbb774695260af 100644 (file)
@@ -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);
index 69e01977a1dd0cf14466bb397bfe6e0b27c11f36..83f0ea929d3d90971aa9aea7ad5730778ab1276d 100644 (file)
@@ -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>");
index 6118bdad244f272b6cc359ca9306c47fa6dfd7a0..a99456c3dd872a783578e7f78c7a3ff4cb316fad 100644 (file)
@@ -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)
index 540f0c6fc160d5d1dc4074e2142c1ea8417f7a4e..3932d081fa2106865db2d3689f9fdb74634d3b70 100644 (file)
@@ -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,
index 83516e3369c90ceda6449d1a86e9b90f20a9b27c..f8408d6e961cb7243b6d2f862701697c47532d49 100644 (file)
@@ -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)
index 7ec4b864a5508d64dc02613ece2f00384014b322..75ec5e7cf50d454f7868142d9f7c6233da0b8461 100644 (file)
@@ -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.
         */
index 3f94ddbf4dc0db10261077a55dd142fcbf8a4eb4..923e640d604cc4f32693e218a20ec0fef4db4fa2 100644 (file)
@@ -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;
index 95dd39ffb2309d340097946be548e55cf5dadfae..b0b36154636508e9f947c8358140f42fb7cbd1d5 100644 (file)
@@ -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,
index b9680ba5a32523df25e453b8d847a785fe35def1..0ffde69c8d015e12db0e5943078b225fbfbd40e1 100644 (file)
@@ -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,
index dbaaa99a0d43fb81f14f7d3a4c6c8b2f3caabd80..f4ad60c97eae4b0f271923694b19dd187416445c 100644 (file)
@@ -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,
index d52728b3c436e1d9d2d97ff0746fd7a845be6c4b..77c070de621ee09145ea9c94dca1a8e1c0f9b831 100644 (file)
@@ -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         = ,
index 7dfe88398d7d3937cd6f308fb6d08b6943ee58d5..5e4748e855f632f198adadda71221306fe6d4bcc 100644 (file)
@@ -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,
        },
index ff26b54bd3fbb79f2220ebd8799f5819f73baba1..87abb4f10c43a4e08d99e5d35a60a9eae158837d 100644 (file)
@@ -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.
index de50547c187d7429c755db17fc4f4242f2599894..7c94c089212f9ffe638b0628ffb1635be407c19c 100644 (file)
@@ -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)
index d5596926a1ef5f9735d64012d84679dd7fdde815..d89b6ed82c51ac37d18dda4bfdd9937a0605c7f7 100644 (file)
@@ -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);
index c2e420a84d2247bd928799151d8418f3b664f735..fbe5363cb89c5c04ab4d76224dce4ce096eb691b 100644 (file)
@@ -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;
index 9e0c1eed5dc5fd6041e8173c1c13c5f835fd34cc..6ce4412fcc1ad90b676965effafa7af65d012648 100644 (file)
@@ -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);
index 3e5b7509502c6321b9065e14a39156b547b83878..7c87105ca04999d55d4fea2f5f2adc9d3846a660 100644 (file)
@@ -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,
index 6893a65ae55f179104381d70dbb6021842e3498a..cbd6a529d0c0d94d130dfb16f8703db6c1139fb4 100644 (file)
@@ -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,
index 876beceaf2d7154f07d9de46bbb75fba3b1f0c43..653487dc7b52c58d69f42723cd5e572dfddc90a0 100644 (file)
@@ -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,
 };
index af8b4142088c3d6a9114fd8c218336f54fcbcc19..3466ca1e8f6c0c11edc26a06b86b83595ed014a0 100644 (file)
@@ -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,
index f97719c48516a037db795c9ee0879c526a062037..b5499198e0290dd329e44486c5d54a1db3a1f893 100644 (file)
@@ -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);
index 5296cc8d3cbaaf2dc20994a71a200b2d6e547cb7..34d05bf72b2e0e403e3568d7eb2193535d8fda6c 100644 (file)
@@ -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
index b07311eaa69386d3cdbad86537da599b5dcaccb7..7fb7e178c74eaacd1af8c1597b02cca0b15676ee 100644 (file)
@@ -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);
index 4c4fe5b1a29a5422cb272cd9ed7e26ae9ec5eee3..39ab4d09faaa2eb500748466ba6ab0fbe4074ac9 100644 (file)
 #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;
index c2367158350ec8680da96b1ff8ecfd1099debd18..bf829ee30077ac0b4716f6ca04101669aea549af 100644 (file)
@@ -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)
index 04e622fd468d89acdaa758b4492434730fea0e0c..fbaed4fa72fa01798ec058b2381c9af381839eab 100644 (file)
@@ -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,
 };
 
 
index 6fa74d530e44d390ce87946b8327a476e5a728e5..0be5844d637266035299014f85b8b1058944cd43 100644 (file)
@@ -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)
index 10468e7932dd5ae54947279dda6345e45f16df8e..4ca2c196c98a1e79a77434e7ba56c14c2e98801c 100644 (file)
@@ -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;
index df450616ab37a2547dbd728e8b0d26c7e4f394b4..6098fd4adfeb89ef5ed9c15407799ddbdcf02e7a 100644 (file)
@@ -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,
index 6407d0d77e810f038da14dfdf1447bae50794a8c..67a679aaf29adf949a2b8dfa79e230b308807615 100644 (file)
@@ -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);
index ddba83ef3f4468ddc5471b3b04ddeb314c0d4c7f..c4b8ced8382989ac539ea9458f74082f0e735866 100644 (file)
@@ -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
index eaa1db9fec32ccbd8fad0b2e501b78f38a741138..537902479689a85f7fac4a260d2827e760fd7485 100644 (file)
 #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
  * 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_ */
index 2a179d087207e4375afb0d66f712043a10417786..58f094ca052e088c521a94059a92349d2533b1eb 100644 (file)
@@ -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))
index 9e9e78a5c4d7e1721a6542908eada4dd04084011..74b98110c5b45c6549d63c9ab76f36f040b9e340 100644 (file)
@@ -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;
 
index 28a6b28192e302227a9b02552c0acef56e6ea560..49cc1ac4f0573b446a7a8c1228cf09760fa3f266 100644 (file)
@@ -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 */
index 2a0c9dc48eb38a5a3a85a06145ae12ce3db84309..fc48e000f35f62ab46c071a4e401ff61f176fce2 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include "qlcnic.h"
+#include "qlcnic_hdr.h"
 
 #include <linux/slab.h>
 #include <net/ip.h>
 #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;
-}
index 0bcda9c51e9bcbc42abde3c0130f00371613389e..de79cde233def0a88f9bab32e2bfab295f7d785b 100644 (file)
@@ -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 (file)
index 0000000..6f82812
--- /dev/null
@@ -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);
+       }
+}
index 24ad17ec7fcde46a6f11491873546f8ffbb3cef2..a7554d9aab0cc2b5a7804fcd3e97ac6b4da01182 100644 (file)
@@ -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,706 +1871,148 @@ 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)
+static int qlcnic_check_temp(struct qlcnic_adapter *adapter)
 {
-       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);
+       struct net_device *netdev = adapter->netdev;
+       u32 temp_state, temp_val, temp = 0;
+       int rv = 0;
 
-       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);
+       if (qlcnic_82xx_check(adapter))
+               temp = QLCRD32(adapter, CRB_TEMP_STATE);
 
-       vlan_req = (struct qlcnic_vlan_req *)&req->words[1];
-       vlan_req->vlan_id = vlan_id;
+       temp_state = qlcnic_get_temp_state(temp);
+       temp_val = qlcnic_get_temp_val(temp);
 
-       tx_ring->producer = get_next_index(producer, tx_ring->num_desc);
-       smp_mb();
+       if (temp_state == QLCNIC_TEMP_PANIC) {
+               dev_err(&netdev->dev,
+                      "Device temperature %d degrees C exceeds"
+                      " maximum allowed. Hardware has been shut down.\n",
+                      temp_val);
+               rv = 1;
+       } else if (temp_state == QLCNIC_TEMP_WARN) {
+               if (adapter->ahw->temp == QLCNIC_TEMP_NORMAL) {
+                       dev_err(&netdev->dev,
+                              "Device temperature %d degrees C "
+                              "exceeds operating range."
+                              " Immediate action needed.\n",
+                              temp_val);
+               }
+       } else {
+               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->ahw->temp = temp_state;
+       return rv;
 }
 
-#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)
+static void qlcnic_tx_timeout(struct net_device *netdev)
 {
-       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;
-               }
-       }
+       struct qlcnic_adapter *adapter = netdev_priv(netdev);
 
-       fil = kzalloc(sizeof(struct qlcnic_filter), GFP_ATOMIC);
-       if (!fil)
+       if (test_bit(__QLCNIC_RESETTING, &adapter->state))
                return;
 
-       qlcnic_change_filter(adapter, src_addr, vlan_id, tx_ring);
+       dev_err(&netdev->dev, "transmit timeout, resetting.\n");
 
-       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);
+       if (++adapter->tx_timeo_cnt >= QLCNIC_MAX_TX_TIMEOUTS)
+               adapter->need_fw_reset = 1;
+       else
+               adapter->ahw->reset_context = 1;
 }
 
-static int
-qlcnic_tx_pkt(struct qlcnic_adapter *adapter,
-               struct cmd_desc_type0 *first_desc,
-               struct sk_buff *skb)
+static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev)
 {
-       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);
+       struct qlcnic_adapter *adapter = netdev_priv(netdev);
+       struct net_device_stats *stats = &netdev->stats;
 
-                       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);
+       stats->rx_packets = adapter->stats.rx_pkts + adapter->stats.lro_pkts;
+       stats->tx_packets = adapter->stats.xmitfinished;
+       stats->rx_bytes = adapter->stats.rxbytes + adapter->stats.lrobytes;
+       stats->tx_bytes = adapter->stats.txbytes;
+       stats->rx_dropped = adapter->stats.rxdropped;
+       stats->tx_dropped = adapter->stats.txdropped;
 
-                       skb_copy_from_linear_data_offset(skb, 12,
-                               (char *)vh + 16, copy_len - 16);
+       return stats;
+}
 
-                       copied = copy_len - VLAN_HLEN;
-                       offset = 0;
+static irqreturn_t qlcnic_clear_legacy_intr(struct qlcnic_adapter *adapter)
+{
+       u32 status;
 
-                       producer = get_next_index(producer, tx_ring->num_desc);
-               }
+       status = readl(adapter->isr_int_vec);
 
-               while (copied < hdr_len) {
+       if (!(status & adapter->ahw->int_vec_bit))
+               return IRQ_NONE;
 
-                       copy_len = min((int)sizeof(struct cmd_desc_type0) -
-                               offset, (hdr_len - copied));
+       /* check interrupt state machine, to be sure */
+       status = readl(adapter->crb_int_state_reg);
+       if (!ISR_LEGACY_INT_TRIGGERED(status))
+               return IRQ_NONE;
 
-                       hwdesc = &tx_ring->desc_head[producer];
-                       tx_ring->cmd_buf_arr[producer].skb = NULL;
+       writel(0xffffffff, adapter->tgt_status_reg);
+       /* read twice to ensure write is flushed */
+       readl(adapter->isr_int_vec);
+       readl(adapter->isr_int_vec);
 
-                       skb_copy_from_linear_data_offset(skb, copied,
-                                (char *) hwdesc + offset, copy_len);
+       return IRQ_HANDLED;
+}
 
-                       copied += copy_len;
-                       offset = 0;
+static irqreturn_t qlcnic_tmp_intr(int irq, void *data)
+{
+       struct qlcnic_host_sds_ring *sds_ring = data;
+       struct qlcnic_adapter *adapter = sds_ring->adapter;
 
-                       producer = get_next_index(producer, tx_ring->num_desc);
-               }
+       if (adapter->flags & QLCNIC_MSIX_ENABLED)
+               goto done;
+       else if (adapter->flags & QLCNIC_MSI_ENABLED) {
+               writel(0xffffffff, adapter->tgt_status_reg);
+               goto done;
+       }
 
-               tx_ring->producer = producer;
-               smp_mb();
-               adapter->stats.lso_frames++;
+       if (qlcnic_clear_legacy_intr(adapter) == IRQ_NONE)
+               return IRQ_NONE;
 
-       } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
-               u8 l4proto;
+done:
+       adapter->ahw->diag_cnt++;
+       qlcnic_enable_int(sds_ring);
+       return IRQ_HANDLED;
+}
 
-               if (protocol == ETH_P_IP) {
-                       l4proto = ip_hdr(skb)->protocol;
+static irqreturn_t qlcnic_intr(int irq, void *data)
+{
+       struct qlcnic_host_sds_ring *sds_ring = data;
+       struct qlcnic_adapter *adapter = sds_ring->adapter;
 
-                       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 (qlcnic_clear_legacy_intr(adapter) == IRQ_NONE)
+               return IRQ_NONE;
 
-                       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);
+       napi_schedule(&sds_ring->napi);
 
-       return 0;
+       return IRQ_HANDLED;
 }
 
-static int
-qlcnic_map_tx_skb(struct pci_dev *pdev,
-               struct sk_buff *skb, struct qlcnic_cmd_buffer *pbuf)
+static irqreturn_t qlcnic_msi_intr(int irq, void *data)
 {
-       struct qlcnic_skb_frag *nf;
-       struct skb_frag_struct *frag;
-       int i, nr_frags;
-       dma_addr_t map;
+       struct qlcnic_host_sds_ring *sds_ring = data;
+       struct qlcnic_adapter *adapter = sds_ring->adapter;
 
-       nr_frags = skb_shinfo(skb)->nr_frags;
-       nf = &pbuf->frag_array[0];
+       /* clear interrupt */
+       writel(0xffffffff, adapter->tgt_status_reg);
 
-       map = pci_map_single(pdev, skb->data,
-                       skb_headlen(skb), PCI_DMA_TODEVICE);
-       if (pci_dma_mapping_error(pdev, map))
-               goto out_err;
+       napi_schedule(&sds_ring->napi);
+       return IRQ_HANDLED;
+}
 
-       nf->dma = map;
-       nf->length = skb_headlen(skb);
+static irqreturn_t qlcnic_msix_intr(int irq, void *data)
+{
+       struct qlcnic_host_sds_ring *sds_ring = data;
 
-       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;
-       int rv = 0;
-
-       temp = QLCRD32(adapter, CRB_TEMP_STATE);
-
-       temp_state = qlcnic_get_temp_state(temp);
-       temp_val = qlcnic_get_temp_val(temp);
-
-       if (temp_state == QLCNIC_TEMP_PANIC) {
-               dev_err(&netdev->dev,
-                      "Device temperature %d degrees C exceeds"
-                      " maximum allowed. Hardware has been shut down.\n",
-                      temp_val);
-               rv = 1;
-       } else if (temp_state == QLCNIC_TEMP_WARN) {
-               if (adapter->temp == QLCNIC_TEMP_NORMAL) {
-                       dev_err(&netdev->dev,
-                              "Device temperature %d degrees C "
-                              "exceeds operating range."
-                              " Immediate action needed.\n",
-                              temp_val);
-               }
-       } else {
-               if (adapter->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;
-       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);
-
-       if (test_bit(__QLCNIC_RESETTING, &adapter->state))
-               return;
-
-       dev_err(&netdev->dev, "transmit timeout, resetting.\n");
-
-       if (++adapter->tx_timeo_cnt >= QLCNIC_MAX_TX_TIMEOUTS)
-               adapter->need_fw_reset = 1;
-       else
-               adapter->reset_context = 1;
-}
-
-static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev)
-{
-       struct qlcnic_adapter *adapter = netdev_priv(netdev);
-       struct net_device_stats *stats = &netdev->stats;
-
-       stats->rx_packets = adapter->stats.rx_pkts + adapter->stats.lro_pkts;
-       stats->tx_packets = adapter->stats.xmitfinished;
-       stats->rx_bytes = adapter->stats.rxbytes + adapter->stats.lrobytes;
-       stats->tx_bytes = adapter->stats.txbytes;
-       stats->rx_dropped = adapter->stats.rxdropped;
-       stats->tx_dropped = adapter->stats.txdropped;
-
-       return stats;
-}
-
-static irqreturn_t qlcnic_clear_legacy_intr(struct qlcnic_adapter *adapter)
-{
-       u32 status;
-
-       status = readl(adapter->isr_int_vec);
-
-       if (!(status & adapter->int_vec_bit))
-               return IRQ_NONE;
-
-       /* check interrupt state machine, to be sure */
-       status = readl(adapter->crb_int_state_reg);
-       if (!ISR_LEGACY_INT_TRIGGERED(status))
-               return IRQ_NONE;
-
-       writel(0xffffffff, adapter->tgt_status_reg);
-       /* read twice to ensure write is flushed */
-       readl(adapter->isr_int_vec);
-       readl(adapter->isr_int_vec);
-
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t qlcnic_tmp_intr(int irq, void *data)
-{
-       struct qlcnic_host_sds_ring *sds_ring = data;
-       struct qlcnic_adapter *adapter = sds_ring->adapter;
-
-       if (adapter->flags & QLCNIC_MSIX_ENABLED)
-               goto done;
-       else if (adapter->flags & QLCNIC_MSI_ENABLED) {
-               writel(0xffffffff, adapter->tgt_status_reg);
-               goto done;
-       }
-
-       if (qlcnic_clear_legacy_intr(adapter) == IRQ_NONE)
-               return IRQ_NONE;
-
-done:
-       adapter->diag_cnt++;
-       qlcnic_enable_int(sds_ring);
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t qlcnic_intr(int irq, void *data)
-{
-       struct qlcnic_host_sds_ring *sds_ring = data;
-       struct qlcnic_adapter *adapter = sds_ring->adapter;
-
-       if (qlcnic_clear_legacy_intr(adapter) == IRQ_NONE)
-               return IRQ_NONE;
-
-       napi_schedule(&sds_ring->napi);
-
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t qlcnic_msi_intr(int irq, void *data)
-{
-       struct qlcnic_host_sds_ring *sds_ring = data;
-       struct qlcnic_adapter *adapter = sds_ring->adapter;
-
-       /* clear interrupt */
-       writel(0xffffffff, adapter->tgt_status_reg);
-
-       napi_schedule(&sds_ring->napi);
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t qlcnic_msix_intr(int irq, void *data)
-{
-       struct qlcnic_host_sds_ring *sds_ring = data;
-
-       napi_schedule(&sds_ring->napi);
-       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;
-}
+       napi_schedule(&sds_ring->napi);
+       return IRQ_HANDLED;
+}
 
 #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)
+int qlcnic_validate_max_rss(struct net_device *netdev, u8 max_hw, u8 val)
 {
-       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 (file)
index 0000000..12ff292
--- /dev/null
@@ -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 (file)
index 0000000..341d37c
--- /dev/null
@@ -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);
+}
index 58185b604b729c131c9215bbdf9c8cfbbb53f24c..10093f0c4c0f3d507514da946df9047b3d68d925 100644 (file)
@@ -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;
index b262d6156816134e980c81915b23e10b526d8803..f80cd975daed2b84a31af47db58b828d28139638 100644 (file)
@@ -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,
index 557a26545d758df2cbcf196e1e9cd2306ae2315e..63c13125db6c9d0a58dcc70438d4af4058bcfd1e 100644 (file)
@@ -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);
index 609125a249d9484835f77fd445e6a8ba32e299db..cb6fc5a743cae91cde7484ef94d1e329928df88b 100644 (file)
@@ -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,
index 3ed7add23c121df0b0a6577ed2ff4c5d327d941d..5dc1616301277346f9d5a931d89c82b340470442 100644 (file)
@@ -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,
index e02f04d7f3adb24112149238885a0b302a0d3faf..9f2d416de750882485ec5b4c5a60f59c2a55e98d 100644 (file)
@@ -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);
index 0edc642c2c2f4c1d9a90d94d1db07c1a63c0a1bd..040b1373994749264374f0a9c44e217ae1997edf 100644 (file)
@@ -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 */
index 927aa33d43497eae636a6d3b4a0e93e15fc93b27..ed96f309bca8e030a0c098df8b8e728314f04bb0 100644 (file)
@@ -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);
index c8bfea0524dd304408642b5df86c3119d7a6a65c..3d705862bd7d1176ec62235bc7fadc508b9dddbc 100644 (file)
@@ -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;
index 2ed3ab4b3c2d61648633596662cf47489172d289..72fc57dd084d1a6b57a9301a8ae2bc43a3ffd249 100644 (file)
@@ -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,
index 6a40dd03a32f16b2289db8605daf1f77e564a3f8..3aca57853ed470034d46e9eb01a848b761fbec28 100644 (file)
@@ -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",
index 4d15bf413bdc89f060964c8114d4486be337ce46..0fde9ca282696f53af4f32b8df32fed0cc0398e9 100644 (file)
@@ -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;
index 25906c1d1b1590825502bc192dffa1aa8d8e494e..435b4f1e348886b0294cfc2fb75c9ff0ecb25eac 100644 (file)
@@ -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
index e11f2ecf69d9b5dfd0ae5600e33bb0fe1d7382fc..945bf06e69ef11c636849ed1f20263868a6b0947 100644 (file)
@@ -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
index 4f86d0cd516a3db2b4eff785d59d1f1a7c07a978..bf57b3cb16abdbc1e89e8aaa83c99a9c47888552 100644 (file)
@@ -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);
index f11170bc48bf4f292d38c4ac5c31a55db10499ee..50247dfe8f574d2a7184c8ea675b5ecabdcc37cc 100644 (file)
@@ -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 */
index 90f078eff8e60d86b491763c7a2b40edf7012052..8e61cd06f66af16a693e5ba47e3b4ef29bf17ddd 100644 (file)
@@ -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)
index 12b573a8e82b6a083da1bd86c714a37792624c1f..49bcd196e10d04b4bac011ba20e652756833c543 100644 (file)
@@ -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,
index 751d1ec112cc5d5e96f3755dec9482c8956457c8..96759aee1c6c2fcb372f83a3f3dd844d39489e97 100644 (file)
  *
  * 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
 
index aea43cbd05200acc1f19cd21e9f96d9e26782ca2..0095ce95150b9915b59cfea2344519879ca63ee5 100644 (file)
@@ -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);
 
index 576a31091165492879ee22edbfd00eee4972047a..2d756c1d71425823100f572065e224a59ca16813 100644 (file)
@@ -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);
index aab7cacb2e34a87203d199be8df72c20020b0e0b..0ad790cc473cb1697e71bd422af0e0086c0242a9 100644 (file)
@@ -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 */
index 438cef11f7270bd620ed04c42fb1c8ee8a9d3621..1b0003323498502741f2c36d5437586a8e8176f6 100644 (file)
@@ -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);
index 9e0ad1b75c335c0bf014fd1b47962c6719705767..d780a0d096b4c5b0b87036c6404089309592d43b 100644 (file)
@@ -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;
                }
index ce72ae4f399fdf3861262967aeb8222d5856bd85..2069f51b2aa9a1412f342b7654a6fb21ae17d9ee 100644 (file)
@@ -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);
index 84b41bf08a38a22ad8e9f0954ec32631628b4ad7..ba40f67e4f05da34c89475a68622375646da9dda 100644 (file)
@@ -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,
index d49b53dc2a500a2602093a2df63daba5c5ad2538..90f8d1604f5fbc8c6e7d1153169b99e97388e901 100644 (file)
@@ -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);
 }
index 3e5519a0acc7ebcccb897ed3719b8506a3b585ba..dc171b4961e47f2a0b0b3247701da908d1dbd601 100644 (file)
@@ -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)
index 53efe7c7b1c066e7ce749bcbdfe53a773d262874..79ad9c94a21bf4b660c1cdaa60352d97facfdbec 100644 (file)
@@ -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;
index 32e55664df6e3d0dc7dd384fb763beb74cccb4ae..b2315324cc6d77cbd97195b923bbb4952b1d5bc5 100644 (file)
@@ -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,
 };
index d8166012b7d4f2fe4c72203a54b1b5c2c356f1ee..9a9c379420d120049bb43e53da5849be904d234d 100644 (file)
@@ -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)
index edf5edb13140fb5908f0197298d17cf3b1cb7503..5bffd9749a58e0e658a7413cf39ea7d21697756e 100644 (file)
@@ -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,
index d01e59c348ad4d75be016850070e8ba03ccd30c7..03b256af7ed5f8c68a75a47cea63cf8f6bc7bb2e 100644 (file)
@@ -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,
index 8d15f7a74b4520cc57d43a034900cc76fcc25282..59a6f88da8676154b34526aa42c0feb34314a014 100644 (file)
@@ -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  = {
index 3269292efeccb3440b22c7fbaf7235ba691ea98e..d51261ba464243c936b0baaa3eaa6f8a68c6091a 100644 (file)
@@ -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 */
index 318adc935a53f72db7a354888aa5b5f65e11bf69..022b45bc14ff15eae3703df8131938212bd0bf68 100644 (file)
@@ -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,
index 5f53fbbf67be84acf2c1fe1e4f0e8541bce86617..370e13dde115a31a1bd4feba15d1c264b8fcdbef 100644 (file)
@@ -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
index c53c0f4e2ce311cc5083d218bff9f5d1ed8e56e0..4616bf27d5150fc5b54a114c7d91f4aac15f8122 100644 (file)
@@ -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,
index 1fcd914ec39b376bd79445c14deba77e3dae73e9..3c586585e1b3f62d3b1eaab29d3bdcbaf4fa6b65 100644 (file)
@@ -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,
index 9f448279e12a52ea7965c3500bd910c859afbb6b..1164930a40a5400ef9681b8cdc78b56f705e8c4d 100644 (file)
@@ -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
index bc965ac9e0250e61f3d4a904989b4d6288abb86f..c8e8ea60ac19f1bc5d9ae56033e41fafec4e3c7e 100644 (file)
@@ -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
index 719be3912aa9ca5cb7b0a527811df460c257561b..186d1480612210d39d26b05305243d8fc71e1c16 100644 (file)
 #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 {
index 0e4cacedc1f0e0cf44fad3bb84c5bac000f8e6ee..7ad56afd63247a9e3c73c27c923109e48e5f638d 100644 (file)
@@ -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__ */
index 033500090f552aedbbc7bddb99e6acd77395ef69..bf83c03bfd06f3699164de132968622690a10965 100644 (file)
@@ -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,
 };
index e49c9a0fd6ffe9a8ad52f19134e2e8c1aa7dcd2e..ab4896ecac1c531814aec2e07fbe199b5e965495 100644 (file)
 #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 */
index 4e0e18a44fcce7bc5a3c35c1eb1f560afb07d77d..491d7e9306037a119ae1cb5e4454935213cc01e8 100644 (file)
@@ -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);
 
index 7d51a65ab09960ac34baa8baa0b2a3a640a9dfc5..023a4fb4efa5769cf1953e44f9f1ca88b2a372b2 100644 (file)
 #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;
index 76fd61aa005f18060806fd16430c56c869ac21dd..1372ce210b58b60aa32325b08a8da2d93b5abb6e 100644 (file)
@@ -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)
index c6cdbc4eb05e613cd499cc35af4ee56300cafcf8..542edbcd92c715c3e0474f321f92de632725e173 100644 (file)
@@ -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;
@@ -1024,6 +962,38 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
                                   priv->dma_rx_phy);
 }
 
+/**
+ * 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.
@@ -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;
index 1f069b0f6af592342ecc1f6a023b9334acc4099b..064eaac9616f59a03e178a259371d1a10c14b7ca 100644 (file)
@@ -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,
index ed112b55ae7f95a587150a0f5ed23d58ca318f97..b43d68b40e50f6156ea10ccfad3f0924d04d1b01 100644 (file)
@@ -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 (file)
index 4ccd4e2..0000000
+++ /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 (file)
index aea9b14..0000000
+++ /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__ */
index c8251be104d6ad6bde2d37b6cea7f2a0c9810429..4c682a3d04240b47efb71736b6a234fdf30cb8cf 100644 (file)
 #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
index 275b430aeb75daebc70cdaeec7695954168d6a04..a0bdf077946614e50fcf30379d18c8192767b6f9 100644 (file)
@@ -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 */
index c9c977bf02ace45e1e4be1b863d682995d39185f..be82f6d13c5199228053ca37a69f847821542f35 100644 (file)
@@ -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);
index 6c8695ec7cb9846fc0a53bbff830ce839fa95a21..5f3f9d52757dbffb60eb277d45acdc6a29eb49f6 100644 (file)
@@ -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;
index 73f341b8befbe2e719ce131168c6ceda4f269a48..a1bff49a815549e862bcaf0d938deb24558d0e54 100644 (file)
@@ -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)
index aeded7ff1c8f96ac9903f33c784aa6e594726858..1dcee6915843cd67f11169eab68c36fbbeb51a4c 100644 (file)
@@ -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)
index a108db35924ed9f0aa943db43e94b2a5fac33f50..e1b8955308277fae7c953274492e3d9eb936f961 100644 (file)
@@ -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;
index 6ce9edd95c04d9ea88826ad8c871f0549f2b85fd..1e4d743ff03e7b86e0cd72002166f0dc28212b73 100644 (file)
@@ -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,
 };
 
 /*
index 2c41894d54726e86b70ee9d4e8aba4c6200437b5..4426151d4ac9d7bd3415bee2ac97e9944ac4f633 100644 (file)
@@ -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)
index 91bd8bba78ffb872faa4b4f60cc43196e4893773..c65148e8aa1d4810e00cbe6d7448fa72572847d7 100644 (file)
@@ -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
index 860c2526f08d0dd470b777756ca4db1d93094a62..d9625f62b026cd06bbfdff222af8950b90bd3027 100644 (file)
@@ -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);
index df55e240374646e2f076d9b4764fab6dc0a07bab..40aff684aa23af64fc3ff03f0c5a54df798c0484 100644 (file)
@@ -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)
index ca0d48a7e508059fd35b6c7bff8cd24295caadbf..0e9ccc2cf91fefce7bda15f6c9ad4ee580e6aa5d 100644 (file)
@@ -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,
index a95b37beb02d56e809c15239247085304c6a2cba..2bd09cbce522dc222fb5a72f9691d368a3b57094 100644 (file)
@@ -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 (file)
index 0000000..3377667
--- /dev/null
@@ -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 (file)
index 0000000..e1bba3a
--- /dev/null
@@ -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
index fce89a0ab06ed14d7168c1fb135574908d5461b0..2a3e2c56bc60ef8a8d2a959086c13d75b8494f96 100644 (file)
@@ -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,
 };
 
 /**
index 51a96dbee9accbae9dbe32e8eb3d81a367819307..cca25509b0392113c7c6f359836ba837607dbd96 100644 (file)
@@ -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)
index 3e6abf0f27714e4163bcdd6f959f057dbc5d3388..22725386c5de78fd94afb6715f30ed0bf24821b0 100644 (file)
@@ -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;
index 5ee82a77723b2537e38094e90e76b6c595158f70..e321d0b6fc882a4969a1a45ef2ce4b7a5de29864 100644 (file)
@@ -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;
index 961c8321451f5551e85847076dcdfb845c51342a..d568af1eb4f4b4a49cbe032a39f6b7cf8b8ee3da 100644 (file)
@@ -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;
index c1ebfe9efcb383080cb868996e4dc6fcb39e25bb..f1b91fd7e41c9b088de874e98dc3101c6942af61 100644 (file)
@@ -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
 };
 
 /**
index 651a70c55e6e69aa40aa62fa77ee7b955dd0dba0..9819349eaa1e88a1a3cfe2ffd3958b9665ee5b20 100644 (file)
@@ -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,
index 0459c096629f0b71df679cdf2fa2bd28449f0d26..7992b3e05d3dd5a48f7701114a2264d23f3ce4e8 100644 (file)
@@ -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,
 };
index a46c19859683ada38d0be5f4d3cf4020d8b0c7d8..1bc7f9fd25836643771c58bc2977eab640ee021f 100644 (file)
@@ -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,
index 2c08bf6e7bf3b326f828585a3a8fefc96d62ddb3..35238389032669576f0080a17d1dd56a4919737e 100644 (file)
@@ -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);
index 88943d90c7653565283a064e3a8ed25f65d5d213..9d1d986f8d409bf8cc87a43acbeb2270b3b8594a 100644 (file)
@@ -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);
index f8e351880119674c0c10b270a45fdf47469dd702..aad909d793d75c2817a00ea580f7303e7ba37257 100644 (file)
@@ -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",
index a788501e978e116908cf0e7a0c92745c275b2009..d9f69b82cc4ff638981798e23bbe3c0e9e6329f1 100644 (file)
@@ -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",
index 77cfe5110318ab7c1dd40bac9c0dd18ad37c8610..919b983114e907242bc49ce64ba95eb00c3e2008 100644 (file)
@@ -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);
index 477d6729b17f7f391c34a520bc08f8031bfbd4ae..d3ebb73277bed4306363aaa20b9ea699d49bcc20 100644 (file)
@@ -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);
index 6695a1dadf4e32d592118feea843eb33aaa5f327..502c8ff1d985b80dd96423040e54fc54dedabaeb 100644 (file)
 #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);
index 3d9a4596a423d22029992830e01cecc3dd09efe6..d5bd563ac131e59362b7df5c33b25f5266f9370f 100644 (file)
@@ -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)
index d4719632ffc687ec6e3aa69b52cc5de337b49bc8..e5b19b05690967ed93f9ac50be4d1548911bf38a 100644 (file)
@@ -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)
index 928148cc32207a90da8cf173258c0ef8cc2b7e36..2b657d4d63a8cc86950db8f50c805c3f96e017d1 100644 (file)
@@ -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:
index ba753d87a32f5120a8ebf1a8e8641273259db65f..a4a62e170ec08533773881189eeaea63c4a0cdf0 100644 (file)
@@ -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,
 };
index 7d39add7d467712f8cb21ec9aee4d01cd6606c7f..1e9cb0bbf62cbcf0c4738388802560ab961f0657 100644 (file)
@@ -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,
index e7456fcd0913fbaf09d146112d9d3c9ab539cae0..b8d22173925dee1aed62df3ccd4d23deb44b976b 100644 (file)
@@ -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,
index ed7521693980e43241a71b6369b0a22b7b8ab460..3f2c7aaf28c4be64356cfc0149dfc486389ae380 100644 (file)
@@ -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)
index e09417df8f39bed4aeebb2f1c6bc2b34cce9e8ed..b5151e4ced612b0847abe72327d6f483d13757fe 100644 (file)
@@ -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)
index c6a0299aa9f912241e6b544727df47913b01db1d..fed4a05d55c77bfd520494b5af8fcaaaffbcce39 100644 (file)
@@ -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  = {
index f83c5b881d2d2c5210af46a7de2b5ec729f5b5c0..5fe1f4dd3369917d5531135d6f39784fc6dc5294 100644 (file)
@@ -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);
index 4b746d9bd8e7e74b227e0ea6bea63193c9942c21..9448587de4531c79517f05d0928b36163d474325 100644 (file)
 
 #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,
index 624ac1939e857a90a71d66d6dd22e5bddffe71f9..24aefcd840654aa10ca97cee1f7b323d9d7a404e 100644 (file)
@@ -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,
        },
index a926813ee91d53b93efe008781f3ba8f47a88aa8..5290952b60c25235f13f308f5041b68795083971 100644 (file)
@@ -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;
index 1a89fd459dd51110cc0a08931ad917f1e4850a8e..f9033c6a888c8ab7f14a4c1db884d35e14b42923 100644 (file)
@@ -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;
index 9021d01317277143110542b5c68b9073e349421b..2f99f8881dfc4c53eb209e888f2f496f97450989 100644 (file)
@@ -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,
index b3321129a83c6dc33180fbbb07aadad296f14554..6989ebe2bc7902c44e429dfefda4c432d3eb7131 100644 (file)
@@ -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;
index 81c7bc010dd8752fbe2ac97ff5326408ebadaa21..383e8338ad865c3d8fabf5c9722fc883ac3923de 100644 (file)
@@ -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,
index 24e05c43bff872e34e35e1deb4d385884057ae4a..7490b6c866e685072f8bef2c0b63a090b4061b10 100644 (file)
 #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,
index 2ed1140df3e9fc0afbc25bce03e5a6eba7ceb228..27274986ab56eb7580788bd376f1b3893388d173 100644 (file)
@@ -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,
index eefe49e8713ca633c8383b1c388826f45e5c9e0c..0c9accb1c14f6a4abbb62641b6ec14fbb07a28ad 100644 (file)
@@ -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);
index 9061ba622ac4c44223eb170e4bd0c5c34ae0d79e..9733bd239a866d4a38552c8c41fb9b9864b6e50f 100644 (file)
@@ -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);
index d4015aa663e6422f7be98e6d8f7f07f1561592de..09297fe05ae5fd6e1d666d500ac06b6ec4d9a3fc 100644 (file)
@@ -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)
index c1ef3000ea6065a9c394ae1fef99e0fa76bd852f..044b5326459fe807fc53e7af30de56c630c5cad3 100644 (file)
@@ -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);
 
index 2165d5fdb8c0f08675772f8dded60f3a15ac34ba..b983596abcbb740bb6416646afe0f401dbf0eaa7 100644 (file)
@@ -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 },
        { }
 };
 
index 88e3991464e7e1531934bcb562718e97abcbfb9b..11f34813e23fb5423ccf90cf9d25e208ed2275f3 100644 (file)
@@ -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,
index 1c3abce78b6a2bdc5f212f31a8779dd012be107e..41eb8ffeb53d72b4357a02782238e0c34bdb42f7 100644 (file)
@@ -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)
index eb3f5cefeba3c6ddcbd53a44cb63a759d9b803ef..0b2706abe3e3b06dbd158eff440d8c2ccc4fb50b 100644 (file)
@@ -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);
index 58f13adaa5490793ebb01be90b38482ee92ec53b..ae7cd7f3656d04174b74ae534814029795217f18 100644 (file)
@@ -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);
 
index 0873cdcf39bebb09d75b1cadbffce4c2d614f593..2ac2164a1e39bd70b0a046ee6dc7df05b76e1045 100644 (file)
@@ -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);
 
index c1ae76968f47ee5fa0191d07f53c4b6eddd09078..ef976215b649330d0c6873b8185f3fefc34b1651 100644 (file)
@@ -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
index bf063008c1afc240a8854c75c3de42d22e7d93b9..478691326f37fc3303199a07dd9e83ae087615be 100644 (file)
@@ -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
 
index 774d9ce2dafcefa699311c8f33532cebd3187dc8..50d167330d384e76b8d3ebfe9cd15cd26dd45c87 100644 (file)
 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)
index 33ab824773c5a795dc49cc91fd28e67bb3e501a5..7a6e758f48e738e4652cc11ea39cd2d913d5f4b9 100644 (file)
@@ -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 (file)
index 0000000..42f51c7
--- /dev/null
@@ -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");
index 74fab1a4015657b52bd5b4c690990120171dc509..d38bc20a60e2e63fd2d056b9070cdce57f524090 100644 (file)
 #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",
index e0433ce6ced7aedaf7d4e39d87aeb1c39c6a42de..3f554c1149f36d2cf3221ee38e4f02507d566ba7 100644 (file)
 
 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)
index 8de641713d5fcbfdfac05bc6475d86c0d596bd64..ace9e74ffbdd90ece5da77dab76890d46877a344 100644 (file)
@@ -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 = {
index cc7e72010ac383f1d0981302df50dc7f388ab40c..3f3f566afa0b7fb54a65481dbbae27ba8a168e5f 100644 (file)
@@ -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)
index c062a3e8295c12d5f69158026b3055522f0f5422..93e0716a118c309f90859e4ee913d2e2e32b41e0 100644 (file)
@@ -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)
index 4584b9a805b3b044b0261871def65c6b5cf13c03..0fcc8e65a06800a390b2aab1ab4ff1f7486cd051 100644 (file)
 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
index c27d27701aee2e2ce0d7e22f077c579da2ee1b07..18dd4257ab17eaba7115ab33fe3bef2743f38a63 100644 (file)
@@ -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;
 }
 
index b77ae76f4aa8f96bbbcabb2d2c4eac5a837d3c29..251a3354a4b049b2299233aa90606f400e5ccf2b 100644 (file)
@@ -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>
 #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);
index 362cb8cfeb92b6021f48995226117ccd0c971faf..9b736701f854e33ae4b8ee4391f5f2135625da45 100644 (file)
@@ -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>
 #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)
index 2ff9815aa27c5e9e098dd587e8291398f2dce25f..f360ee372554d5b1ce40c789aac44a6d066fc730 100644 (file)
 #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)
 #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)
 
 /* 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)
index edb81ed06950624a182ad1e298f2f54d142804e7..c04110ba677f5febcac3876a411646845b3a9ab3 100644 (file)
@@ -1615,6 +1615,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)
index e522ff70444cd0d7e8f1ce34132055e438ded7ce..95814d9747ef1988657ccd72bc01d56501bc7b37 100644 (file)
@@ -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);
index cbf8b06253528e9e5557c31e844581d7334d7e21..68d64f0313eaa38d3324213f536e820365f16f93 100644 (file)
@@ -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,
index 0ae1bcc6da730fecd4267f0076b3f3ef422ea7ce..dc8913c6238c965b0905ef7ad6784bf669f06388 100644 (file)
@@ -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
index 8b5c6191707626ba64bad7bdceeab2c299e5bcfc..3b3fdf648ea741267800a2b49eee87d835d2370a 100644 (file)
@@ -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;
index eac709bed7ae54473067d334e76fb4484f4f478b..df70248e2fdafe36e09d1c026e4c034094165264 100644 (file)
@@ -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
index ef36cafd44b72138436ce3175dd5dfca7d184082..851dc7b7e8b0a650482df9b86d2abf50d666e67a 100644 (file)
@@ -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);
index b6271325f8035c33ebaabf5e172f9ef9725780ba..56941d6547eb33388535ead21ffb808354027de2 100644 (file)
@@ -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,
 };
index cf4903355a34eb78b6bbdd488b9c35849f0afe97..62f01b74cbd65d1f6899f37dfe21a99735bcce74 100644 (file)
@@ -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);
index e2779faa6c4f9c651cc115dae455dd72423f19c9..6269a09c736950c98d7df37ec4261d548d53f1c6 100644 (file)
@@ -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);
index 760776b3d66c0033cae82c73c18fcad8fd7b57d5..fc9d11d74d605de87107d9b8642732dd1944f7da 100644 (file)
@@ -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);
 
index f5d533a706eacc690d87a7260e9b0189ccad3800..7ef435bab42550ee4f220333e192be158634e875 100644 (file)
@@ -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);
index 5fe246e060d7b8288f933e8f83856eade0e37271..53efc57fcacebd776ff810108a48e619c79eca03 100644 (file)
@@ -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;
index 9659fcaa34ed5001f973f62ed600aebc4e314885..ddbce54040e2ca5e0a49c3fbde8b77528499c792 100644 (file)
@@ -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;
index feb7541b33fbb8191928581eaaacc024dc193e5c..6a24a5a70cc7d4459e04e0348882f0324dd4fad3 100644 (file)
@@ -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;
index 73aae2bf2f1c886180b5074085acd610c0415cab..21565d59ec7b5f5351608a5fbcf7e22de3475fb7 100644 (file)
@@ -35,6 +35,7 @@
 */
 
 #include <linux/hdlc.h>
+#include <linux/hdlc/ioctl.h>
 #include "wanxl.h"
 
 /* memory addresses and offsets */
index 4b66ab1d0e5cf8f9e0fb9511c145e0049585172f..6702da838b0ebc7b434267b18d595d696cc03799 100644 (file)
@@ -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;
        }
index 154a4965be4fd9922e62684d73467b87fa46194e..3d339e04efb7a760af7b887e31f7956973df424d 100644 (file)
@@ -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,
index 3cd05a7173f6ce37945c04237d3dc493aa080647..53295418f57616e3d1c891ae8bdf5446a40c9e2e 100644 (file)
@@ -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 &&
index 99b9ddf21273b2244b2a8f9e03847a68a736bb61..77fa4286e5e98d2034fcbda6c0d786c3b455c50e 100644 (file)
@@ -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 */
index 09602241901be1c391ae78e1f6f0eac84c28f502..1a67a4f829fe9f3fca15a6ad3533e335bec70a25 100644 (file)
@@ -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
index d716b748e57440311b1912b6b99ba99930ed32f4..1e18621326dc2fc5c70335e43e4e781436820a84 100644 (file)
@@ -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 (file)
index 0000000..0d320cc
--- /dev/null
@@ -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 (file)
index 0000000..ebf7f3b
--- /dev/null
@@ -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 (file)
index 0000000..7157f7d
--- /dev/null
@@ -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 (file)
index 0000000..00c6fd3
--- /dev/null
@@ -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 (file)
index 0000000..0fe2c80
--- /dev/null
@@ -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)
index 338c5c42357df7fa9e9f0e2db4dedddeaaae9d61..c9f81a388f1572cb6a9f233809731f61c4ffe209 100644 (file)
@@ -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
index aec33cc207fdbba47e67a6aa28a52ac19f4bfede..8e8bcc7a4805914ba64888ea683c13b3b76ddb0a 100644 (file)
@@ -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);
index 9f31cfa56cc092cfb9dca9647b3ef7aad62175c4..30ca0a60a64c020e6b3609bff361078e03b6a89f 100644 (file)
@@ -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;
 }
 
index b9f708a45f4ed97bb65a47a7f11dcf0da2b09872..f77ef36acf87fba68a70d74b0a05cfae367fd442 100644 (file)
@@ -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;
index 7a28538e6e05ba6c001e9b04aa913955a339ac44..4264341533eae5384af1a675db255496fa559245 100644 (file)
@@ -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) {
index dff48fbc63bfd1d7a4cc5aed6c2632c6128c77e9..859db7c34f87f07fdce6b19b1e2ce20b4061f208 100644 (file)
@@ -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,
 };
 
index 0c2dd4771c365b798b7eb7b26eba79ddb4554c79..4084b1076286ebd20720a4276ff05bee3a8ac3c5 100644 (file)
@@ -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) ?
index d755a5e7ed2036b9f7e237431413cd093fed07fc..26c4b72208597ba5c91f5be60ba3c753ce38c97f 100644 (file)
@@ -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.
index 8cae8886f17dc4eb667f107b49ef4af5c674369b..cab0ec0d5380afde712ac83bf23a2eaab514cbb8 100644 (file)
@@ -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
index 7089f8160ad5bb7f2a7377bbc0adae68229274b2..5516a8ccc3c6809589ff1d1fd8756859f504f7e9 100644 (file)
@@ -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 |
index 780f77775a9152ca078922cbd2a7754c9a019d24..e5e70f3a8ca866f1e4c1c40c8e9ff04914b49692 100644 (file)
@@ -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,
index 82c4dd2a960e5077f7a9f11e1201cabf3b75be04..4b46adbe8c923b7dd410c919dc3cbc289541ea4f 100644 (file)
@@ -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)
index cec49a31029aa9711682d1ede1f862c58aa8ed30..189d8faf8c87f8bd36b16d8d40e568aa90fc98f5 100644 (file)
@@ -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 */
index 49639d8266c28a25a186cfe148c70a5ef0c3535f..f97cd4ead543fdd239220372cc6846539343d1c6 100644 (file)
@@ -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 */
 };
 
index 68ed6c2665b73387cefbc1edf0985a94b7ad36a6..a6b614421fa409814e1662a78df1507da904b970 100644 (file)
@@ -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:
index cd0e1ba410d6ac3050fa5bb3fd35f99451492238..fbb78dfe078f692ad94c34d80bf9dbf7ec2e3a06 100644 (file)
@@ -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) {
index f9626c723693ca84e7c3efbaccd0fa47de49916b..ba6bd497b78701f4d53a939b7343e766ca0088a0 100644 (file)
@@ -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);
                                }
 
                        }
index f90b5db741cf74c6784a9dc0a6a100d2b7a59f08..f21fa322e5ca3e7245a994ebce2dc0ce48c82c7a 100644 (file)
@@ -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)
 {
index c189e28e86a9bbfaebb7f81a32291801d51fa1f7..bd50b6b7b49267665e8854e388dd068fab63707b 100644 (file)
@@ -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 (file)
index 0000000..3a8d5e9
--- /dev/null
@@ -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));
+}
index 05b95405f7b56131b4cbf49a66d165a8f661861e..d111980d44c0bb9b550b0733322b663a6842c6c8 100644 (file)
@@ -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);
index 7dfa0fd86d7b111ea06cbd1c85d673ba65717cb6..78b369286579dd954f98243a24e948db2a4f3c2b 100644 (file)
@@ -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;
index 3740c3d6ab8832a89fa397ac0e4e903e81782f66..62bcc0d5bc23d73493694984cd7e8aa202291635 100644 (file)
@@ -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);
index c30ab4b11d614c8188afc53d61ad3dee8b29a9ba..998f8b0f62fd59e4d6507216bf257f0ed4776dcf 100644 (file)
@@ -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;
index 43339aca585d96508cc9d2b7f87b4cf743cca3c9..98b1755e67f41f41f2af6f06ff6747731572aaca 100644 (file)
@@ -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);
index c7aa6646123e9ae0db4de0a83cb80b97aa322ef6..5fc15bf8be09449cffe2a7b19a47843ad615af7b 100644 (file)
@@ -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
index 6f7cf49eff4d0d1dd3bd6e6b954ec5c507969a44..262e1e036fd730fe63f273001aff016ac600e0cf 100644 (file)
@@ -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},
index 84b558d126caf6d01d883fbbb6325aeae58ff286..8b0d8dcd76255239e7451b4a1258adca79ef8342 100644 (file)
@@ -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)
index 5bbe5057ba18ae35408c2aa78dfbdf4d5cefdf0f..562186ca9b5248a26c7cb957357d80f0d5f162fb 100644 (file)
@@ -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,
index 41b1a75e6bec7c120264f526ccd1426cca4828a3..54ba42f4108a4347c30900499b5c3e09c5dd4bbf 100644 (file)
 #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,
index 1a36fa26263966e34bc6b952ffc64a0426387b11..74fd3977feeb845adf93f6ed0fd650d506ca2ee1 100644 (file)
  */
 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);
index 44c202ce6c66bb12544ddd6673abd6405962f5cc..8dd069259e7b7ea7d9dd40212571cab73424f131 100644 (file)
@@ -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;
+}
index 2a2d01889613a610a8cb6084e6f0705234867123..66d7ab9f920dbccf15739e4511ae3089330acda4 100644 (file)
@@ -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
index 0ed3846f9cbb36e8aa1f67eab09dc9e5f219b0c8..09c1f9da67a05d9bbc1f715b61f31ee62bb23f00 100644 (file)
@@ -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);
index 759f5f5a715469bb43c054b45d4d8ed5f6917302..ce19c09fa8e84aec2877e2f14861b0284f4d958e 100644 (file)
@@ -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,
index 9a48e3d2f231eadefcf15dc2604d891150b389fb..10795629848871cbd2e34df016102fd9cfe920f2 100644 (file)
@@ -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
 #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
 #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
 #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
 #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
 #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
 #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
 #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
 
 #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 */
index 1d8235e19f0fcd15afe2b114d39f28da2ce10390..f69d292bdc027403aa7400bce554899a41462a0b 100644 (file)
@@ -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},
index 58f30f65c6b62fa21acb46f2468f171cc7736125..ccc42a71b43642f668aae77158c697e66af85896 100644 (file)
@@ -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},
index fb4497fc7a3da1e87547cda3e8a7fe76497504c8..a3710f3bb90c5b0fe8a02cc26455ec31b3697162 100644 (file)
@@ -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 */
index 843e79f67ff25740745c16a09002100019bb13d6..0c2ac0c6dc892f31a84be30f7332a6eb4267a9f2 100644 (file)
@@ -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},
 };
index dfe6a4707fd22684a5994de3b6c4d9dcadd456f2..86e26a19efdac1923395543c1a50fb53a6cb8958 100644 (file)
@@ -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;
index 1b48414dca95d919a3c66dc6c760ce0b7338abdc..531fffd801a34eaa11b8d483aca51ac07e7a7fab 100644 (file)
@@ -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)
index 419e9a3f2feda6c20fc7a504120f26b0820bb9ca..9963b0bf9f72694630cab058621547f53eeeb237 100644 (file)
@@ -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);
index 385197ad79b006f494c3659dc88efb343038c184..6de26ea5d5fa11e190d89edd92dcec24058e1f75 100644 (file)
@@ -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
index e5cceb0775749661360e4aef376d8eb05c4615a7..1e8508530e984487cfce4aba50df5e6af8b0873b 100644 (file)
@@ -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++) {
index 1060c19a50129a2f8a2e94a4d4fd331e0ebc85e7..60dcb6c22db91032a859b3f110c22fb3258d7817 100644 (file)
@@ -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
 
index ad14fecc76c6e1eb1405448a2b1179f2a4f234b0..5f845beeb18b86210d3aebf9f52fdcfff87e1462 100644 (file)
 
 /* 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
index 6727b566d294a43073c2a4cf3cc532f0e633b34e..13ff9edc24015e5e2126fc4f6c7fde8dcb003c90 100644 (file)
@@ -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;
 }
index 2ed9785a38fa0467a8ab8be32d30c912a5194a87..375c3b46411eee6cd140dbc22e6e435fe0e32ad9 100644 (file)
@@ -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 */
index ea2a6cf7ef23a86241a1232d9294eef6392f9c13..24877b00cbf4b7b97a534daaf1cc0316d8928e8c 100644 (file)
@@ -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);
index fd0328a30995f3fbed6f3d8d9467813553a22bc7..cda52f39f28af81cb5afb18e6d406b46d9078864 100644 (file)
@@ -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);
index 0512397a293c9a50a41cb61389f6aeb1c6da2d7a..971d770722cf239bde42cdfedc5fe0fa6c52c7dc 100644 (file)
@@ -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,
index 319c651fa6c5298d66d6d4a44969b569aafcf5aa..40d4f62d0f163304810d642d42095975ecc61786 100644 (file)
@@ -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,
index 7d075105a85d7b0300f167ec02cb03ac85c3fad2..c2bfd748eed81a99a150743985e4d6b1eef45621 100644 (file)
@@ -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;
index cd742fb944c274528ee5cfce31625ba329f42b55..3ae1f3df063758f000519a5f7d08984e8fb474b2 100644 (file)
@@ -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;
index a8ac30a0072089a594abf849d00ff41105afa078..1c25368b3836f756f39c7f17f884ba43a2fb233c 100644 (file)
@@ -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;
        }
index d9ed141a053e6a885fcdf031866f9daa1e5918d2..4b412aaf4f3699e65396598be9f7485f2af0754f 100644 (file)
@@ -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 */
index b30596fcf73a57ed5e63d81d2b465b7e4e4b7f48..96bfb18078fa14b0013d4b3e93e7544b16639746 100644 (file)
@@ -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;
index f42d2eb6af99302f449ef44beac8f0120238e73d..d0ce1f5bba1022087ebd45fbf7275b83c4db39e5 100644 (file)
@@ -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,
index 3035deb7a0cdcd5343c09733942bf0d56e5886a8..87110de577effcafa57cbfba7adad21b67bc2973 100644 (file)
@@ -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);
index 0eacfc13c9155feb4af8cb7c4d1e4b1918c0cd39..105582d6b714956e124b291b56480d0c3c0adb6e 100644 (file)
@@ -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:
index d98255eb1b9aa4f1809df6d7c9b1b2d6eb2b141b..05d5ba66cac3588f64e8f6ab0545af76fbf88cbb 100644 (file)
@@ -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 |
index ca78e33ca23ec1393dd6fa9b109a7443cf865cf8..9c07a8fa5134bb4611b93b9645c20fd0e0c414e3 100644 (file)
@@ -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);
        }
 }
index 06cdcb772d786038b7f1e5219349a6a682b216c9..b6a5a08810b83f6b06e568e998e11e6711b9e8e4 100644 (file)
 /******/
 
 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;
 
index 1829b445d0b01852ea11111692174c766b3c7e55..7cb787065913f7ee118909c2b372a8e07651f38c 100644 (file)
@@ -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;
 }
 
index dbc1b7a4cbfdc0eeca59efa19f4d52e7e09044ec..7f1a8e91c908c2dea314a7171e1d1d59139e6c6a 100644 (file)
@@ -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);
index fad3ccd5cd91aa8ab5b96603701275303a3f6392..f69ef5d48c7b96119cb516259f41f2256f150747 100644 (file)
 
 #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;
 }
index 7b88b9c39ccddc4ef4e3aeafb53e437d0f35a0ce..ade3afb21f911e86589e325c2e99b49b7fe91289 100644 (file)
@@ -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);
+               }
        }
 }
 
index dd45edfa6baec25304af0a07ccea22f1c0910f29..be30a9af152884d8e073b7a3be5b79e6b3d5a8ee 100644 (file)
@@ -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
 };
index ec2d7c80756753f02e37f30ac3d42b45ec463259..5c02702f21e7e1d3508b493ca89499b0226ce2c4 100644 (file)
@@ -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);
+               }
+       }
+}
index fc14eea034eb640c95d4332849c2646a176aa7e3..06958837620c250a263f1cb4ddde8330e2333fa7 100644 (file)
 #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*/
index f088f4bf9a26a0802ca4526dce91b48213fdd09f..7ae73fbd91361092f1a0590be0cbc2e2b0ecc9a4 100644 (file)
@@ -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);
index 27ed80b5488133175a0b348a3f9752ebe69ed016..714558d1ba7883dfa450105b8347b3598983b99e 100644 (file)
@@ -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
 };
 
index 268e67dc5fb2d945a26a332081b32167d9e133dc..267dbfcfaa96b8cb8b5311bd484d8e9908f838bc 100644 (file)
@@ -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);
index 83d16e7ed27239bfa4734a2b1b66e98b2800dbf4..d4df98a938bf4755d1af6238d41e5df0753970c6 100644 (file)
@@ -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);
 
                /*
index 4e6760f8596d2dc07543ab36d419c1977c3c95ec..ad3c82c091775a7011f7a0638da7522e15685c83 100644 (file)
        (((_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
index a483d518758cfe4d57f1b38c8e8812b3ce3d8a74..9f8563091bea436d5973331edac261de73292035 100644 (file)
@@ -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);
index 741918a2027b56ebe0f561d5175e8a129b8a3059..90e48a0fafe5a3ca6e12be66e6b0402bdf7feaf0 100644 (file)
@@ -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;
index 267d5dcf82dc61b5e992a524338965a29f979c56..13a204598766d1d3ea49f665c8ad42be78decc2d 100644 (file)
@@ -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
index 24ac2876a7337ad2a015f69a4f273165d3d8d7f0..aaebecd19e5975f449bdd73bcc9c73411b6f37af 100644 (file)
 #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],
index e3b1b6e87760ed0e70ca77dfcb23ae3e4b9df982..24d75ab94f0d36a22f7d025eea336d5197f83f2b 100644 (file)
@@ -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;
        }
 
index a0b72307854799b81c36649d916da2940be90ad6..4684dd9894961a84dca6cf0f8abe099b6eb8fe92 100644 (file)
@@ -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)
index 84377cf580e06a29a69d4ca469ed5736f4aa9936..ef4ec0da6e498288cafe11ff6770b6eaf96d13e8 100644 (file)
@@ -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);
index 888152ce3eca98193b01147a827b4daee59c7ff3..307bc0ddff99091a1f224bb236013a1a90b5fa76 100644 (file)
@@ -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);
 
index 19befb33107348e949cf958c05ee2683f9ba28d9..39e8a590d7fc86feb3dd70cb55a21d7a6c63e335 100644 (file)
@@ -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;
index 4a4e98f7180777c97b9a9cc0ec10fcdc97a46c83..4374079dfc2a031d6faa0a2819c69e1b9c49885f 100644 (file)
@@ -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);
index 51e33b53386e58a3d85c180d271c1678b8b08a01..c1b159ebcffee4412987c4ba1d22cb080c1ea8d4 100644 (file)
@@ -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));
 }
index 777cd74921d7d721aa875b51ad07b006f697ecda..38bc5a7997ffd43b9a8c8f45a6329fe4ffdac5c1 100644 (file)
@@ -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;
        }
index c5a99c8c81687de1b26a79bb2ad777c4d71c2029..16ab280359bd9ffbb9ee68770606d949b3060e6a 100644 (file)
@@ -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
index 714cad649c45b68281ae7c2c1e7f66e7c317c52c..f2ea2ceec8a97b6b6fb33819912a0923163d6065 100644 (file)
@@ -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,
 };
index 3533ab86bd363982e4ffd5f73e7e7af1dacc70d6..a73ff8c9deb55ff320f5e3ba46ac6b0fc8dabef1 100644 (file)
@@ -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;
        }
index a54fb2d2908905729be68920664710a84c46f6b3..59a5218006946bdafd36e770dba63be9d4d3cdf5 100644 (file)
@@ -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)
index 136510edf3cf819285d8f72f5cb3afff0ee3683e..8cb206a89083aaa314868ef2c07b906181fe6689 100644 (file)
@@ -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;
index a29da674e69ddbdc9982a104bc0bb0660fc488f4..482476fdb1f39299062d5a8bb3857ccafe45dc1a 100644 (file)
@@ -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;
index 18e208e3eca1c4be2ec3e7a8bbf02056d71132ff..8c3f70e1a013078ea85c92a2ac0447e6abd9f754 100644 (file)
@@ -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;
        }
index b8ffea6f5c64743df59f78c94d40093b8fbeb5ea..849a28c803023e03570d69ca8d6de8f60462a6c6 100644 (file)
@@ -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) >>
index c9d811eb6556bfa4494155391398c2bb2b1df815..1d92d874ebb61e487a33a2a8827e864ef39f1a15 100644 (file)
@@ -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"
index 9d5170b6df50ec3f05902856684efab2149b09e8..1a6661a9f008122f52288556b09237572ae71bf6 100644 (file)
@@ -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
index 3b2c4c20e7fcfcccaa2a6706108473f805c0f13b..be35a2f99b1cf3fce453e89bdacddacc84806ed1 100644 (file)
@@ -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;
index c3247d5b3c222bfcc6ab8a05236515be073f55b6..d33e5598611bbad54808a69aa85b492137ce9df9 100644 (file)
@@ -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 */
index 17e7ae73e0089600780a54a35ab0e7c75dc08a87..fd672bf53867f6b7aac803fae15686d0d750ccee 100644 (file)
@@ -23,6 +23,8 @@
 
 #define BRCMF_VERSION_STR              "4.218.248.5"
 
+#include "fweh.h"
+
 /*******************************************************************************
  * IO codes that are interpreted by dongle firmware
  ******************************************************************************/
 #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
 #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
 #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
 #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_ */
index 9b8ee19ea55d12ccf45a644e139490dd5d2b4843..dd38b78a9726f75861bcb1f92ef3d511a81b92db 100644 (file)
@@ -43,36 +43,89 @@ 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);
index a5c15cac5e7d4c1357c20f9dc2956ea4ab51ea14..83923553f1ac2cff41acda4677a5fd7cb54d7efd 100644 (file)
@@ -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 */
index 15c5db5752d199d2ec4c78913c44a5713dfb78a8..f8b52e5b941a7b3c738701a067a92eae2b84c7e9 100644 (file)
 
 #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;
 }
index 7f89540b56da1f3885d28a6a8be61a0cf395a4ce..57671eddf79dda2a204ed0da5ece8524d91733ba 100644 (file)
  * 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);
 }
 
index fb508c2256ddc8a7244b61ad1e6b3fd13b41bf30..f2ab01cd796600643c94f6e98da09429d2cbedaf 100644 (file)
@@ -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
 #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) */
 
index d7c76ce9d8cb3d74dccb79c863e5db1efd9a7446..74a616b4de8e027c5f877f2910a526fed9d29aa3 100644 (file)
 
 #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>
 
 #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)
 {
index 6bc4425a8b0f7ed40b3dbf43d513bcb0629802e6..48fa70302192d3f7e6c18f001f00b22dc176b009 100644 (file)
@@ -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_ */
index 3564686add9a1099aa048c5ba4526f5052288abd..cf857f1edf8c3b84d2d92c5f2b41874fae88ea82 100644 (file)
@@ -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;
@@ -1804,15 +1785,6 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
        return rxcount;
 }
 
-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)
 {
@@ -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 (file)
index 0000000..ba0b225
--- /dev/null
@@ -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 (file)
index 0000000..36901f7
--- /dev/null
@@ -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 (file)
index 0000000..d8d8b65
--- /dev/null
@@ -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 (file)
index 0000000..16eb820
--- /dev/null
@@ -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_ */
index 9434440bbc6536054b592588f9ef4d1bce73bd22..b1bb46c49799f6391503fdca17ee81116eb32583 100644 (file)
@@ -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;
index 7a6dfdc67b6cc5ed11ce8e5281cf45c5fa81818a..914c56fe6c5f72ec260e27779ebac182b3d2dd0a 100644 (file)
  * 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>
 
 #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
 
 #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);
 }
index acfa5e89872fb8c8103ebb626beef5c0ba0064a2..f483a8c9945b1cc049eb2223039a522974dd61ea 100644 (file)
 #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 {
index 481345c23ded3250bf68c002089809e815abb3fe..1261a9b84e04aaf348df15e8bb2ad0e00a213255 100644 (file)
 #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 */
 #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,336 +477,39 @@ 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");
-
-       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;
+       brcmf_dbg(TRACE, "Exit\n");
 
-       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);
-       }
-}
-
-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;
-               }
+               brcmf_dbg(INFO, "MPC : %d\n", mpc);
        }
-
-       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,
@@ -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,259 +2359,37 @@ 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);
+       clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
+       clear_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status);
 }
 
-static void brcmf_notify_iscan_complete(struct brcmf_cfg80211_iscan_ctrl *iscan,
-                                       bool aborted)
+static void brcmf_cfg80211_escan_timeout_worker(struct work_struct *work)
 {
-       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;
-}
-
-static void brcmf_cfg80211_escan_timeout_worker(struct work_struct *work)
-{
-       struct brcmf_cfg80211_info *cfg =
-                       container_of(work, struct brcmf_cfg80211_info,
-                                    escan_timeout_work);
+       struct brcmf_cfg80211_info *cfg =
+                       container_of(work, struct brcmf_cfg80211_info,
+                                    escan_timeout_work);
 
        brcmf_notify_escan_complete(cfg,
                cfg->escan_info.ndev, true, true);
@@ -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");
-
-       if (test_bit(WL_STATUS_READY, &cfg->status))
-               brcmf_invoke_iscan(wiphy_to_cfg(wiphy));
+       brcmf_dbg(TRACE, "Enter\n");
 
-       WL_TRACE("Exit\n");
        return 0;
 }
 
@@ -3179,84 +2568,48 @@ 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");
-
-       /*
-        * 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
-        */
+       brcmf_dbg(TRACE, "Enter\n");
 
        /*
-        * While going to suspend if associated with AP disassociate
-        * from AP to save power while system is in suspended state
+        * if the primary net_device is not READY there is nothing
+        * we can do but pray resume goes smoothly.
         */
-       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);
+       vif = ((struct brcmf_if *)netdev_priv(ndev))->vif;
+       if (!check_vif_up(vif))
+               goto exit;
 
+       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;
+}
 
-wiphy_register_out:
-       wiphy_free(wdev->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_new_out:
-       kfree(wdev);
+       if (cfg->vif_cnt == BRCMF_IFACE_MAX_CNT)
+               return ERR_PTR(-ENOSPC);
 
-       return ERR_PTR(err);
+       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));
+       }
+
+       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);
-}
+       struct brcmf_cfg80211_vif *vif;
+       struct brcmf_cfg80211_vif *tmp;
 
-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;
-
-       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;
-}
-
-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);
+       struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
 
-       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;
index 71ced174748a335a72f2c6b68712d9d3e40731d5..e4d9cc7a8e63728dc192d3ba63482dcf412f0c06 100644 (file)
 #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_ */
index e227c4c68ef943e74eb4c35026a9fc397a2f186d..d3d4151c3eda8bdd94f06110f465bfba98a96cea 100644 (file)
@@ -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
 
index b89f1272b93f506f24f8cf9e262f9b7c489c6180..f0888a9ee32e1b62d3b635c4b7aa47ca0b2c09a4 100644 (file)
@@ -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);
index be5bcfb9153bfacca71e4cd226fa2c0224612334..1de94f30564fe8291c99657ced06d33ff6af2e5b 100644 (file)
@@ -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);
        }
 }
 
@@ -1181,23 +1123,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
  */
@@ -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);
 }
index 421f4ba7c63ccf67593248d3927e372b87f72e2e..73d01e5861090d99d875c886ae8783c9dff5561c 100644 (file)
 #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);
index 55e12c3279119facdcf3540fbb39773b47cc831f..54c616919590d2ebc89c5b15e3415c605104833f 100644 (file)
@@ -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");
                        }
 
index 27dd73eef56d6159a458939210df718176b7f359..871781e6a7138a0a9556c029dd8d265ecd53b733 100644 (file)
  * 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 */
index 64a48f06d68bfa124c1687bc1fa81a799fb5be82..a90b72202ec5a298b9cf6483cd5380ae5ef74ef0 100644 (file)
@@ -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 (file)
index 0000000..9761deb
--- /dev/null
@@ -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 (file)
index 0000000..796836b
--- /dev/null
@@ -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_ */
index 5e53305bd9a9bc57901c1a0597b00de32208a57b..1860c572b3c476a88527418725848a62f7f9e45a 100644 (file)
  * 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
 
 #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;
 }
 
index cc269ee5c49995f89d5c5c9a9d0183693935f2f7..ff5b80b0904636661ced2b2896c7730312a734bd 100644 (file)
@@ -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);
index a744ea5a95599797023a0040401ab1816855f77f..1fbd8ecbe2ea293a28d6a65648fe011a2fff3fa6 100644 (file)
@@ -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 */
index 75086b37c817b747fe5482bb097a66a859c14214..17594de4199ef58a30488e2c7579ec02c521d9ea 100644 (file)
 #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
 
 #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
 
 #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;
index 8debc74c54e1a63b5d9be1eae54e3c52d33375ba..fb447747c2c6e9975b681a7d42f0dc6ae5ad00bd 100644 (file)
 
 #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,
index abfd78822fb8a574e0266a2389f7751f9d4fef9b..606b534347bc93984cb9aefb38acd6981f3af8de 100644 (file)
@@ -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;
index 622c01ca72c5d24e8bfc55c3b84ad61633c4bb92..b7e95acc2084033dd5c27de24b80bebd78f8dfbe 100644 (file)
@@ -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[] = {
index 5855f4fd16dcd8d0dc473cd73275baae72414728..4fb2834f4e6483f7c9321666c75598e6f9fa21fd 100644 (file)
@@ -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);
index ed1d1aa71d2d6a3541f285e7155a46d53bfe425b..dd9162722495333df13296c80d89c20ea9058d74 100644 (file)
@@ -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++) {
index e11ae83111e499411670af3ac4fc72158ba77d25..ae1f3ad40d459f7722f57a0c40744e1ea58f6f18 100644 (file)
 
 #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;
index f0d8c04a9c8cd13b03962b8855acdc69f8913b35..fb7cbcf81179bbc31f70e9557def1db9593dffb8 100644 (file)
 #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
index df7050abe717d9c09a6167ade588553a16041e79..d39e3e24077b1dca873f0ffe0dbce6a221dbaaea 100644 (file)
@@ -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) {
index 29b8fa1adefde125d62608f3b9513e53afba247a..d92b21a8e5977c19b528dfe9038d23aec96f708c 100644 (file)
@@ -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,
index 9731252424900e0e5e080ced9c33d2a5ee9a82fe..5fe17cbab1f313c7095595fa0d8a0d31b1435e56 100644 (file)
@@ -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.
index 768bf612533e04317feb756efa17563400ce6ab2..844f201b7b70080b19c4e7ae70bc31f375214a7c 100644 (file)
@@ -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,
index 0b22fb4217359f72414e2e14726d34d683f422e2..6eede52ad8c0fbc0581a2b3a68d302cb589f4dde 100644 (file)
@@ -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,
index c9fe3c99cb003c087729b12380b16df014827f8b..218f2a32de21758e105bb4a12e782e65e11ea90a 100644 (file)
@@ -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)
index 02e057923236bd6133f5008d1c01feb7c911fcda..95a1ca1e895c6de72a7a792b66e32bc137876326 100644 (file)
@@ -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))
index e252acb9c86239aa0b031fad77d465beb4efb86d..d604b4036a764358e52bd2c2ca9d02bd24f14ce9 100644 (file)
@@ -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,
 };
 
index 87e5398943308665618cc85a78aa933fa5d7df48..e0b9d7fa5de0d43d74e130b6c91d4ad0078ecf19 100644 (file)
@@ -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);
index eac4dc8bc879ffabeacf558b576f6a6fe8b5d9ed..c3fbf6717564a3295ea2a87ecdc669e80d2e9d89 100644 (file)
@@ -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,
 };
 
index 2d092f328547d8ca37dfef233a4619c23f7b5aa4..1b15b0b2292b4fe06c3fa1efcc95279c9901370e 100644 (file)
@@ -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 */
index 318ed3c9fe7499899d08fc3de1de917438690109..7e16d10a7f140e4bc0a1414af1ec317f7284b9c6 100644 (file)
@@ -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);
index b4bb813362bdbeb44afab3dd7b73d74dd556feb3..a9a569f432fb3517d5421ea1c4d43cdd96a4d816 100644 (file)
@@ -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)                           \
index 727fbb5db9da0b41b10b6132267d4b91f533f852..5cf43236421ee57a4b3145ded322e49fe05ca6f3 100644 (file)
@@ -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.
index 75e12f29d9eb7dc0e4a16bb92aa5cd6aa587b062..33b3ad2e546bc9c4fbad24516c2ab1d279888041 100644 (file)
@@ -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);
index f2dd671d7dc8cb031f7a121fd920ffa10809c3d7..de54713b680c386cb3287354bf0801de57e47562 100644 (file)
@@ -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
index 01128c96b5d8c309e800bd08b01f378ceb382613..71ab76b2b39d18da16518e99b5d36ab90ac87042 100644 (file)
@@ -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;
index 1a98fa3ab06df6fbf9ae8ec3197680adef182883..5b9533eef54dd7bb173c250ac0eb42666ff06e87 100644 (file)
@@ -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;
 }
index 8141f91c3725bd3c8f26d9830e61574dd3b4586f..2653a891cc7e713ebd7f5708b252f977de4e09ed 100644 (file)
@@ -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;
index da5862064195159a7052fd92b327ce017b2d1381..8c72be3f37c16ad9a8d77c0ef04d8f0face8a8b3 100644 (file)
@@ -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,
index bef88c1a2c9b1a83bfbcfdc584708edfb64e6593..6ff46605ad4fc1c60d34ffedf28dc706f93abd07 100644 (file)
@@ -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 &&
index 2d9eee93c743aa0f7bfe6d98330ccacead4fe201..3163e0f38c25109a3c5f5a2e7c71f39f37b40eda 100644 (file)
@@ -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;
index 408132cf83c18285d4eff4ba7a67add5fde64bda..faa05932efae92e80c322b4a28d606da7cb9808b 100644 (file)
@@ -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) {
index a82f46c10f5ec036ca07ae6bbfa139bb50ab8052..f3dd0da60d8a43247084cd0f798b132e4b28ba7a 100644 (file)
@@ -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)) {
index 5a9c325804f6dcdc8d47d44faf15dec1051d4471..cac4f37cc427531871049d775a6fba7f315638a8 100644 (file)
@@ -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);
 
index 2830ea29050286f1a8d44d43a14ca820810daca9..9a891e6e60e888bc3a49453246a3d064ec4f9835 100644 (file)
@@ -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;
        }
 
index bb9f6252d28fad2d25340845f8f3a324e5d0fc56..610ed2204e1f197d7bbcb22e76de3ec0776fa05a 100644 (file)
@@ -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])
index cd9b6de4273e8c035a8bcdd39bf715316825db90..bdba9543c3516095d82cfc19c9f9123c6debb178 100644 (file)
@@ -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 =
index f5ca73a89870727a71d6a354abebaeb01221d6f5..da21328ca8ed84e9e06e3aebde44fade0973e870 100644 (file)
@@ -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",
index 2cb1efbc5ed1f3d80127f678e4c82e42046eb7c1..c6467e5554f5c2992c27a0871b418680225dfdc6 100644 (file)
@@ -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 {
index 87f465a49df142952139c7446adffdeee801385c..864219d2136aab118c08d95a23472440d94a4b40 100644 (file)
@@ -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 */
index 59a5f78402fce35319014267c33514b7e4b7ef65..dc7e26b2f3835676bd9385a20b187aea6f7b45d0 100644 (file)
  *****************************************************************************/
 
 #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),
@@ -234,6 +301,48 @@ TRACE_EVENT(iwlwifi_dbg,
        TP_printk("%s", (char *)__get_dynamic_array(msg))
 );
 
+#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
 
@@ -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],
index 198634b75ed0e0cb5cb732525b6c9049f1a4b422..d3549f493a17dc60ab49ea649fd06eeab03a8b48 100644 (file)
@@ -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)
index f10170fe879922b6f56a8d2a6b287d11af92421e..471986690cf042eec370ba3e84a9e86730216402 100644 (file)
@@ -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);
index a5e425718f56a052e365dc0e2f11657b2af88bd8..555f0eb61d4886b9fc54a93f86ad64a9b2c787ed 100644 (file)
 #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__ */
index 80604664174722ca4c57703e7e86592b90949b86..ec48563d3c6ad3e05f652ce936ff5fabc8cb2b2b 100644 (file)
@@ -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)
index 3dfebfb8434ff63e9b2ce7a2b2a86a7b01fad281..cdaff9572059bd162beb8e050a0215d3f632ebcd 100644 (file)
@@ -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))) {
index 50d3819739d12bd8296b3be9dec03425a488f45a..48dc753e3742aab857af7f88617b81206dc163cc 100644 (file)
@@ -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);
index 9253ef1dba72d005f407b34c1bfb2665fb9b4be6..c3a4bb41e53370931832e8a7427d3361337e469d 100644 (file)
 #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)
 
index ff1154232885da82add146706ffe67b325d3e9b2..b76532e238c166f9c5095ac1ab5564c1e56a8aa0 100644 (file)
@@ -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);
index 81b83f484f08318c505fb3648ef1a88b15615fcb..f8620ecae6b41dc1a4d05c756c6dbe00b3ec3148 100644 (file)
@@ -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,                           \
index 9fbde32f755922d3e9fe219e1cdf50be3e11fec8..244019cec3e1e8ca22a4c10ff0d0b17836d54cfd 100644 (file)
@@ -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,                \
index d1665fa6d15a0e7ce56fb7dcb28f73b4e7554220..83ca40321ff1e789b9aca2959b1d2b602b0beef6 100644 (file)
@@ -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,                                  \
index 4a57624afc40839a6b95dce82718fb681f21145d..d4df976d470904da3be3f60d0a01f5c4abfbb40f 100644 (file)
@@ -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,
index 2a4675396707474fc0a0ced64009eddb967b4bec..c2e141af353c657c86dc0a8b86dff9a4515a9186 100644 (file)
@@ -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,
 };
 
index 401178f44a3b130a9de6832bf10bd3e9b6e4b529..d91d2e8c62f53e687a7eb4ae513a36035c495e78 100644 (file)
@@ -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";
index bb69f8f90b3b47c441fde750c14d0a9b9a3a6da0..dad4c4aad91f2a461cdebfc9ac879b51a36db827 100644 (file)
@@ -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,
  *
  * 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) &&
index fe0fffd043048f48adca5c110031f537d363d73e..35708b959ad6e563a38d29f1bd75c51e87c9c2c8 100644 (file)
 #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),
index 79a4ddc002d3dac1ce4aa9182bd2a2a0cf76630b..6c5b867c353ae83cd79404bece14d83989cba6a8 100644 (file)
 #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
  */
-void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans,
-                                      struct iwl_tx_queue *txq,
-                                      u16 byte_cnt)
+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
+ */
+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) {
@@ -272,115 +455,541 @@ int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans,
                return -EINVAL;
        }
 
-       if (WARN_ON(addr & ~DMA_BIT_MASK(36)))
-               return -EINVAL;
+       if (WARN_ON(addr & ~DMA_BIT_MASK(36)))
+               return -EINVAL;
+
+       if (unlikely(addr & ~IWL_TX_DMA_MASK))
+               IWL_ERR(trans, "Unaligned address = %llx\n",
+                       (unsigned long long)addr);
+
+       iwl_pcie_tfd_set_tb(tfd, num_tbs, addr, len);
+
+       return 0;
+}
+
+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);
+
+       /* 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)
+{
+       struct iwl_trans_pcie __maybe_unused *trans_pcie =
+               IWL_TRANS_GET_PCIE_TRANS(trans);
+
+       iwl_write_prph(trans, SCD_TXFACT, mask);
+}
+
+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_pcie_tx_stop - Stop all Tx DMA channels
+ */
+int iwl_pcie_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_pcie_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_pcie_txq_unmap(trans, txq_id);
+
+       return 0;
+}
+
+/*
+ * iwl_trans_tx_free - Free TXQ Context
+ *
+ * Destroy all TX DMA queues and structures
+ */
+void iwl_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_pcie_txq_free(trans, txq_id);
+       }
+
+       kfree(trans_pcie->txq);
+       trans_pcie->txq = NULL;
+
+       iwl_pcie_free_dma_ptr(trans, &trans_pcie->kw);
+
+       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;
 
-       if (unlikely(addr & ~IWL_TX_DMA_MASK))
-               IWL_ERR(trans, "Unaligned address = %llx\n",
-                       (unsigned long long)addr);
+       /* This function is not meant to release cmd queue*/
+       if (WARN_ON(txq_id == trans_pcie->cmd_queue))
+               return;
 
-       iwl_tfd_set_tb(tfd, num_tbs, addr, len);
+       spin_lock(&txq->lock);
 
-       return 0;
-}
+       if (txq->q.read_ptr == tfd_num)
+               goto out;
 
-/*************** 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.
- *
- ***************************************************/
+       IWL_DEBUG_TX_REPLY(trans, "[Q %d] %d -> %d (%d)\n",
+                          txq_id, txq->q.read_ptr, tfd_num, ssn);
 
-int iwl_queue_space(const struct iwl_queue *q)
-{
-       int s = q->read_ptr - q->write_ptr;
+       /*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 (q->read_ptr > q->write_ptr)
-               s -= 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 (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;
-}
+       if (WARN_ON(!skb_queue_empty(skbs)))
+               goto out;
 
-/**
- * iwl_queue_init - Initialize queue's high/low-water and read/write indexes
- */
-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;
+       for (;
+            q->read_ptr != tfd_num;
+            q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
 
-       /* 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;
+               if (WARN_ON_ONCE(txq->entries[txq->q.read_ptr].skb == NULL))
+                       continue;
 
-       /* 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;
+               __skb_queue_tail(skbs, txq->entries[txq->q.read_ptr].skb);
 
-       q->low_mark = q->n_window / 4;
-       if (q->low_mark < 4)
-               q->low_mark = 4;
+               txq->entries[txq->q.read_ptr].skb = NULL;
 
-       q->high_mark = q->n_window / 8;
-       if (q->high_mark < 2)
-               q->high_mark = 2;
+               iwl_pcie_txq_inval_byte_cnt_tbl(trans, txq);
 
-       q->write_ptr = q->read_ptr = 0;
+               iwl_pcie_txq_free_tfd(trans, txq, DMA_TO_DEVICE);
+       }
 
-       return 0;
+       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 void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_trans *trans,
-                                         struct iwl_tx_queue *txq)
+/*
+ * 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 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;
+       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;
 
-       WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX);
+       lockdep_assert_held(&txq->lock);
 
-       if (txq_id != trans_pcie->cmd_queue)
-               sta_id = tx_cmd->sta_id;
+       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;
+       }
 
-       bc_ent = cpu_to_le16(1 | (sta_id << 12));
-       scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent;
+       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 (read_ptr < TFD_QUEUE_SIZE_BC_DUP)
-               scd_bc_tbl[txq_id].
-                       tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent;
+               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_txq_set_ratid_map(struct iwl_trans *trans, u16 ra_tid,
+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;
 }
index 1c10b542ab231a45e5134a58ceb858c8ab82d331..ec6d5d6b452e7aebf8b8d782460e7b0263c121a0 100644 (file)
@@ -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);
 
index 4cb234349fbfacc305b1565ed5f1a30ba16aa108..739309e70d8be7872e9272c9e25dcb7e3a5b2a4a 100644 (file)
@@ -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);
 */
index 9604a1c4a74d9ac158d6ea6f4928ed75765fada1..4bb6574f40737f462f3b7f4ad3d9fea3d705b415 100644 (file)
@@ -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,
index 97807751ebcfd59204fe6d651ce6874e52d552be..3e81264db81e937d25b3dda0a5fb7543d4c4379e 100644 (file)
@@ -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;
index 429ca3215fdbf3e0d48f82e3c1eb69381938fd46..ff9085502beacba1f66990b93e225fea6d3d2fa0 100644 (file)
@@ -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;
index 395f1bfd41027f788901b62b5ef4621ac019956d..68d52cfc1ebd250a55a43c8b641344d7d6999461 100644 (file)
@@ -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;
index 9402b93b9a363b350545fb24aad6f67f06afc172..4a97acd170f7bfcb423db64307a113c4c55f6852 100644 (file)
@@ -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;
        }
index 8e384fae3e68a840c274498c2376ab3423d61e89..b2e27723f8016817673cd6890b8546a693521fb9 100644 (file)
@@ -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.
index 780d3e168297fcf80c62e4345ac6d29c22007b73..a875499f89452d7ab4a4307b72c0475d5829f470 100644 (file)
@@ -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);
index ae9010ed58debd4a8dc5001e03cbe866b2c9a8a2..5f438e6c2155e6e8f103ae708791a1be2c1cedff 100644 (file)
@@ -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);
 }
 
 /*
index a870b5885c09364872c597108f019135828d23bf..46e34aa65d1c2dec171e99c5156c57ecd5905a11 100644 (file)
@@ -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);
index dda588b3557063e95bfc92746422e3d3942a1719..4dc8e2e9a889c06b3e8d41b352bc45c8e20efc88 100644 (file)
@@ -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
index b5d37a8caa09a4429504fd804d8a6a5b1542b1af..39f03ce5a5b1cf50bfde4ec291438bc828a2dc22 100644 (file)
@@ -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);
 }
 
index 7b0858af8f5d804d05ae6c8ebd4bc20990a6ffed..88664ae667ba65ea18e9c27410f26095e1931309 100644 (file)
@@ -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);
 
index eb22dd248d5491e0644a7b60225216faeae7ad1a..9c802ede9c3b94cb56f385e7c5c40699d0c2ee9f 100644 (file)
@@ -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.
@@ -411,49 +412,6 @@ static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter)
        return ret;
 }
 
-/*
- * 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.
  *
@@ -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);
                }
index c2d0ab146af545431b8fe5f3d04916756ef3b782..1b3cfc82194081606e21988f7dbc03a53c854df7 100644 (file)
@@ -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);
index 9171aaedbccdb28bf3371efcd5c7c89cecb3ab93..9189a32b7844b713815636d03517e7532da31f94 100644 (file)
@@ -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;
 }
index 82cf0fa2d9f683a391bb2215f94447d53d09ef40..5a1c1d0e5599ab2689b8fee3d1e81d796dead8fc 100644 (file)
@@ -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);
 }
 
index 21033738ef0c664d7c00bcf1babc2eece48832c0..8cc5468654b401f2b116c8963859f1712b299cb4 100644 (file)
@@ -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"
 
index 09e6a267f5666fd0bf868bd537635726239e4680..65c12eb3e5e73ba8085dd6e57c332b5ca6e28a80 100644 (file)
@@ -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:
index 8132119e1a211a41c887a0bda77f433af41a8bcd..41aafc7454ed2b626bded2d96d9f8f9ac143a992 100644 (file)
@@ -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));
index 0c9f70b2cbe61de8b77084fb71135bc7fda36f00..cb682561c43898fd6f27c03ab3aba38adbf269d8 100644 (file)
@@ -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)) {
 
index 07d32b73783ea2cdd0859d80849eed1eb4a94804..b5c109504393d22a3bc5eae4a5510f47f4353b56 100644 (file)
  *
  * 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;
        }
 
index 2af263992e83a23ff30bb6558f85204105bb4180..8c80024c30ff6345399d53e7132bed310a6c12a6 100644 (file)
@@ -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);
index d95a2d558fcfbb2d84950650344c1656db173351..8dd72240f162d9786e4fac374fdf7144307b0ee8 100644 (file)
@@ -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;
 }
index a33fa394e3499cbca7e03b413c00f9afd42e772e..21c640d3b57919792e53406ed94ae7cca96a90e7 100644 (file)
@@ -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);
index 0966ac24b3b422a83b31792c006752776f271344..a018e42d117eb49b9b89716e70910f299de2ef68 100644 (file)
@@ -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);
index 22a5916564b84099576e1c554b37d1fcbcd420b2..63ac9f2d11ae2fb15af3324175b522f36a2792bc 100644 (file)
@@ -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);
index ae88f80cf86b966238dff0544fa97ff7ca83e168..0982375ba3b14c6fbedee1cc6b74a0d2b6eaa9f9 100644 (file)
@@ -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);
 
index 600d8194610e3b0c3c7d6c87a0400a5b290514a4..818f871ae987fc4944741562e18fca47b2fdd156 100644 (file)
@@ -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;
index ec839952d2e77bc01bf57bb63be53086913821f0..b92f39d8963beeaeca0f14800e4a0c06081c893a 100644 (file)
@@ -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.
  */
index 5099e5375cb39ed8e22a7382f6a42bc939c47fb7..f221b95b90b3c2935c67e9c272d5f1c2a89000d4 100644 (file)
@@ -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);
index 7b751fba7e1f90176d797ab1a2bc88ce72e5f6ac..d01edd2c50c505866cb554826659e24b4489c68f 100644 (file)
@@ -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))))
index 4dadf9880a974c5820ab915700385b1e9b6d46ab..5a8fec26136ef338455e8ee71d7583c64cd3bce5 100644 (file)
@@ -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;
index 326396b313a6939c697aa2d8eac59f58119dab6a..d73fdf6185a2c7495891544ffe693ed140432f54 100644 (file)
@@ -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,
 };
index 6058c66b844e5b0f018dd7c96e7adb7745dc3057..677bf14eca844a1dd7c8cc2dca0724e9c5a5b505 100644 (file)
@@ -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,
 };
index 2bac8248a991ee16466fb5194da234f3e43fa4c8..2559dbd6184b2421b95a2d73630e14a887a9525c 100644 (file)
@@ -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,
 };
index 93159d68ec937eb2fa4fed0b6d56db2934792f78..42afeeea2c405c2403f0075f1aeabacd7af57767 100644 (file)
@@ -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,
 };
index 7f53cea2f2052ab8b4f23b53d08c2c8eca35ee20..01624dcaf73ed7f2d77b90b46eb342c5f2576816 100644 (file)
@@ -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);
index 1ef1bfe6a9d7845822cef3413e680de03c2774c9..d43e3740e45d95e4b55bc3af085747dcf346c04b 100644 (file)
@@ -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;
                }
index b4390797d78c1c6917d4ea81e0ddf2f269fbc46f..933e5d9419373529bc2b5428c34e9ea1c49f7331 100644 (file)
@@ -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,
 };
 
index f7929906d4371bd59ccdc0ad14ca6a9d5dff7a39..4fd49a007b513874da70a6e7477f9035552e2b3b 100644 (file)
@@ -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)
index effb044a8a9d5d8169be88744d561c62ac160165..e71c702e2eb18e30640cd193307bb54569410b48 100644 (file)
@@ -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
index 5861e13a6fd8d5f9aa83c24892acfc11a210b02e..12f0a34477f231cff73a591f3bc5a2af300ce9d0 100644 (file)
@@ -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];
index bd1f0cb56085ef94eb5e634a7467f1c12e3a3ffb..abe1d039be814150d1815949e90f78b38573fa2d 100644 (file)
@@ -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;
index e3a2d9070cf655acdfb9758a525c5cc7a71575a9..a2d2bc2c7b3dde238e373e422d1f54051e08b832 100644 (file)
@@ -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,
 };
index 479d756e275b388fc5d17b77bde4303e27117e48..9bea10f53f0a9179d9f2055e3df961c10802e211 100644 (file)
@@ -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,
 };
index 6d67c3ede6513fd4e1be870bbf117cb2d69138dc..4db1088a847fc3a347507e5fece8d600f0cc47ce 100644 (file)
@@ -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:
index 59474ae0aec0d14e7dfc2639c19cf65b82b3b7ea..197b4466a5d2a44378f998fdefa2c221ae6124c6 100644 (file)
@@ -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
index 27829e1e2e38964b2085dc84e30f618b3f72f97e..9224d874bf24b62e017bfe8906f686b929a45db6 100644 (file)
@@ -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,
 };
index 3b8fb5a603f25244241a3219bff169962cf54733..5c149b58ab46dd61b53406511352b3f80f7c48cb 100644 (file)
@@ -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 */
index 69097d1faeb676d97ddd27c7ba7dc3f575cd2f6f..4ffb6a584cd0c406509f8d8bf3ba1f32cf209ad2 100644 (file)
@@ -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.
         */
@@ -1181,6 +1184,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
index 98a9e48f8e4a38e852c54e8dbdef0c2369a753a4..ed7a1bb3f2450223e780e344e014efa51d290dbb 100644 (file)
@@ -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);
index d6582a2fa3534879614a23dd29435e747a0cca0c..f95792cfcf8922e17222fec2feddc34f5117c308 100644 (file)
@@ -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,
 };
index 021d83e1b1d3367d0ff19954324c4306dc6b8f42..1b3c2843221d2a38ded783270009d7838d89b4b4 100644 (file)
@@ -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,
index 7811b6315973cd466e19d2fd2c139532daf04610..4574bd213705c7b51f875d8c8ec2c4bd3dee44fd 100644 (file)
@@ -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,
 };
 
index 6b28e92d1d215c0f598354326b9c1e9780376268..21b1bbb93a7e41452720a6f9ede17cba3951393e 100644 (file)
@@ -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
index 97935c565babd456952ffc2ac9ffbe1a89891402..3b1cbac741e3f4b91c41dd5c0360cb5fe521b88a 100644 (file)
@@ -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__
index 59381fe8ed064064dcddaf697ba26aa345b2c0de..4494d130b37cb0d0ad585eea5142e0c312c86b26 100644 (file)
@@ -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,
index f35af0fdaaf0ae8dc9a44a26a51d6f3480126a1c..5a8c80e259f7f36070f05b096e4187064f829729 100644 (file)
@@ -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
index 5b4b4d4eaf9e9273916131eba6830955a17da5b6..0e510f73041ab88659b131c2a392598046e127fe 100644 (file)
@@ -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);
index a7c0e52869ba3c708cf39685c59489122353b4a0..be33aa14c8afaa6672497d156abebb4b3cd146f9 100644 (file)
@@ -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
index 07493d2957f2a11d313275643b1fee0bc7c6196f..fd3269f476854235993dbcf04990fcab6d43b810 100644 (file)
 #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
index abc306b502ac0348b97dd40eae26c01ebf6947d9..3deacafdcd5ed3c33c1384a9f5e84e4cd08517e8 100644 (file)
@@ -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,
index 241448fc9ed5d190a5a54097571d4f3fc6504870..65b08f50022e64d76dd2956304bf1acf4b02be93 100644 (file)
@@ -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);
index d5cbf01da8ac0de8a1d04fd2ae7502b67d03ab47..c1e065f136baa631a9245b87f897dea167865431 100644 (file)
@@ -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;
index 1ca4e25c143b83026c43fcccc0ddc6723f900605..1cdf5a271c9f3221f8c608201b47b4a6af768585 100644 (file)
@@ -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);
index cdcad7d9f15e5ea4049e74f10f21e6497ebf2d9a..1d5d3604e3e03875f5e9ec4453ad2291c5de3c33 100644 (file)
@@ -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:
index 2925094b2d912529fb32dc5202487d1def6d9910..3cfa1bb0f47676853500b237a37aaeb9e49b1bad 100644 (file)
        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
index 27b3af880d96ed235e163bbfb3defa53a669f3b5..74f9c083b80dc4dee7396cda8e61e3606ecbc1e2 100644 (file)
@@ -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");
index 86d73b32d9956c81f9b43886805bc23cb4adaa10..d1f34f6ffbdfbca5969523c24ba9261f7219ba22 100644 (file)
@@ -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;
        }
 
index 88deae67cc1482a9714ff1e7c263b2063a323395..73262ca3864b2c219a14e3c8085cbdcb32fc32c3 100644 (file)
@@ -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;
 }
 
index 54c7614958a890c1fc2b8dc4149a66101c0a09a3..a9c406f33d0a57ffd818b95b03e61a28cb4ca6bb 100644 (file)
@@ -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]);
 
index ea2e1bd847c847d83b000f808b7cc1d60c99b7d6..49f663bd93ff37c2d6069de4be0bc868427dcb0a 100644 (file)
@@ -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,
index 390d6d4fcaa027654e82ceea0892933751383be6..173424756149b95d7d1bc9ea6eb9981fa6603130 100644 (file)
@@ -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;
index 6fd39eaf361ee2bf5cdbcf70fc45804c6aa4e144..16a0b9e59acf726745d3ad90c5480f2c4151096d 100644 (file)
@@ -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");
index 4bbb711a36c5fd6e4cfa4b14d08009ffaedcad49..b1ccff474c7953f2431cb2cd0390f2e0ebf89591 100644 (file)
@@ -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);
 }
 
index 7e91c76582ec3c5078858a087bfd74422ad95b08..32ff959a0251bdf36cb69122b55a6fc438e3bdd0 100644 (file)
@@ -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);
        }
 }
index 506b9a078ed1885bea8583722d3275a0b5a94c93..953f1a0f853238289620eaedbaf5f80bdc77d3d9 100644 (file)
@@ -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,
index 6e66f04c363fb43ad25557e5149cab6a78a6d933..b6222eedb8350c8eb691cfe5fe1fa8eba8b7eaf3 100644 (file)
@@ -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,
index ed868c396c257d5a5b4a22affcc4c12e401b0d0c..fd8df233ff2299d451c01be3211daf8ed20c28b2 100644 (file)
@@ -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);
        }
 }
 
index db0086062d0574f59018739a8ac3f198c3a4aa34..33041bd4da81f03ffb50c273c7953c989072788a 100644 (file)
@@ -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++;
 }
index 3066a7fb0b57b5147b750300164b6f39ad134b73..20144e0b4142d9f53e9f892a49c415c013160cd0 100644 (file)
@@ -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,
index 480862c07f921668e803694a37ef702f19d34a8d..03c6d18b2e0755fa1bae1236180980eca1a4fb64 100644 (file)
@@ -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,
index 4686f340b9d6095698c0e8b2f3a16f3bd2ae0fdb..f9f3861046c1f6c4deb0a9454b872ca260618f16 100644 (file)
@@ -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,
index 20afec62ce05b2e40105d8150500bf32d5a00e24..2d255e02d795b6cd2a403450f53dfd377664d176 100644 (file)
@@ -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
  */
index 465f581571013f0fdc442b675ff952edae36c071..e551fe5f9ccded4242d75d2c19e4e0051c187dfb 100644 (file)
@@ -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);
index 4542e6952b97a550c7973ceb34cee231e9655ed1..28526a7361f51f76d6eb285106296721413f8d0d 100644 (file)
@@ -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];
                }
 
index 1886c2644a26104d37c99e38709c2dc9a58c8350..a8e068c76e475dd74de6884db4e49b39945e8143 100644 (file)
@@ -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);
index b917a2a3caf75c960c8d1dd5827d74fd4550c2a5..67404975e00b41318722a0df4ee05f47df6a44cf 100644 (file)
@@ -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;
 }
 
 
index 08c2f562512986c9f27dd6f5fd1db282664d32fa..5061f1db3f021072b32a0617385ccb75db427d07 100644 (file)
@@ -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);
index ad4b4803482d307dcf4ac6f39f85839771645d23..cecc377e9e6134ebb2fc709e34981228954485dc 100644 (file)
@@ -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,
index e3cf4c02122a9baaad488c4e02aaf23fcb33f21f..0e9f6ebf078add38ded9595f6a454b8182148335 100644 (file)
@@ -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 (file)
index 0000000..4ed731f
--- /dev/null
@@ -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 (file)
index 0000000..417afee
--- /dev/null
@@ -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 (file)
index 0000000..8c11035
--- /dev/null
@@ -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 (file)
index 0000000..12e2a3c
--- /dev/null
@@ -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 (file)
index 0000000..39d2461
--- /dev/null
@@ -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 (file)
index 0000000..f55b176
--- /dev/null
@@ -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 (file)
index 0000000..89994e1
--- /dev/null
@@ -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 (file)
index 0000000..3d092e4
--- /dev/null
@@ -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 (file)
index 0000000..76f4d12
--- /dev/null
@@ -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 (file)
index 0000000..887d521
--- /dev/null
@@ -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 (file)
index 0000000..4325ecd
--- /dev/null
@@ -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 (file)
index 0000000..0a8c038
--- /dev/null
@@ -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 (file)
index 0000000..6fa24f7
--- /dev/null
@@ -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 (file)
index 0000000..9c4e1d8
--- /dev/null
@@ -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 (file)
index 0000000..2cb88e7
--- /dev/null
@@ -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 (file)
index 0000000..39cc793
--- /dev/null
@@ -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 (file)
index 0000000..e7a59eb
--- /dev/null
@@ -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 (file)
index 0000000..df6ca9a
--- /dev/null
@@ -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 (file)
index 0000000..7a46f9f
--- /dev/null
@@ -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 (file)
index 0000000..2044b59
--- /dev/null
@@ -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 (file)
index 0000000..6e0f3ea
--- /dev/null
@@ -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 (file)
index 0000000..199da36
--- /dev/null
@@ -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 (file)
index 0000000..50dd2fb
--- /dev/null
@@ -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 (file)
index 0000000..d0f9dd7
--- /dev/null
@@ -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 (file)
index 0000000..18b0bc5
--- /dev/null
@@ -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 (file)
index 0000000..fc4fde5
--- /dev/null
@@ -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 (file)
index 0000000..9b0b50c
--- /dev/null
@@ -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 (file)
index 0000000..f5ce713
--- /dev/null
@@ -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 (file)
index 0000000..87331d8
--- /dev/null
@@ -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 (file)
index 0000000..ad05b54
--- /dev/null
@@ -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 (file)
index 0000000..8ed3174
--- /dev/null
@@ -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 (file)
index 0000000..0dbdc52
--- /dev/null
@@ -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
index e3ea4b346889430dfb07d604f052adb6522f18bb..29f0969e4ba00cd3dd299c209ac09f594346b168 100644 (file)
@@ -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;
index 43846b329153195fbe123b884d84e365483aa97e..5235136f6dd2c0ec194a9d7595c9b65b21e19ec2 100644 (file)
@@ -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);
index f1b6bc693b0a28ddddfd89ef50ffa898f3ce24f7..21a5f4f4a13509da671834fe196d0fca19fa2b9f 100644 (file)
@@ -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;
 };
 
 
index 441cbccbd38162bb8b1e83c11fe5fe266897a9c8..f47e8b0482adcc5b49f344a897ff34d80814b71a 100644 (file)
@@ -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);
index 6af35265c900173cc58dcf36c0c68a5b595e3157..23289d49dd31806210566fe2aa737154eecf482e 100644 (file)
@@ -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;
index e2750a12c6f160a922609f775fcf65c4c81d662e..e57ee48edff6d3d788626b618633caab096e0427 100644 (file)
@@ -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,
 };
 
index 567660cd2fcd3f3ead3a5c82baa38f6eed6d3690..3b266d3231a36a538a6c17673c3d9ae18696795f 100644 (file)
@@ -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)
index dadf1dbb002a3ac7bfb904f47e694eb5b5b37c19..e5f5f8f391447ce3ea74a525c5e5a30090b849c6 100644 (file)
@@ -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",
index a39682a7c25f333cefb9bcfc67b632426afece00..8d8c1f8c63b79b8775a70c85fb4b4669380afbb7 100644 (file)
@@ -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",
index eaef3f41b2524b9885084ce33c77afb2a034ceb6..27f83f72a93bb9c946535886043750fbdadee632 100644 (file)
@@ -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);
 
index 25530c8760cb0a07234f753efe66e31fbf107c2d..ea9d8e011bc9d45f5414b43cb6d1e3af492a89c3 100644 (file)
@@ -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);
 
index 73ace4b2604e1c7dad73e7a9217f10ab8932b542..646f703ae739b3b84ebff7316aea31faf8fadfc2 100644 (file)
@@ -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,
index a519bc3adec1d6ade15542ba852918114f5cdb32..f06f4770ce029076b8e622fed5285b0167ef7aaa 100644 (file)
@@ -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)
index 68584aa0f2b0f731e86b7e1a0c0ea973b3a89ebf..c3884937c007cf049b6efe0c5d158008972a7bf9 100644 (file)
@@ -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,
index ff306d763e37a893976e67b9a5502760b208ff4a..71ab320fae821a34b5afc4917f6915248c10fdd6 100644 (file)
@@ -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);
index fc24eb9b3948666b0819156539138958dd6888f1..c26e28b4bd9f985a4d7c6d3307d969bb671bf6f7 100644 (file)
@@ -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,
 );
index bf05831fdf091d372f154c8f7b3ea9e023cdba64..36c359043f5469b8d59b4235d9cea35db79d779e 100644 (file)
@@ -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
 
index 30ae18a03a9ccc650a195547086866a66646cd98..ada681b01a17be24ecfa93b8c0ddf518c32c5c1c 100644 (file)
@@ -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 (file)
index 0000000..7257338
--- /dev/null
@@ -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 (file)
index 0000000..7da9071
--- /dev/null
@@ -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);
similarity index 58%
rename from drivers/nfc/pn544_hci.c
rename to drivers/nfc/pn544/pn544.c
index c9c8570273ab5a58c782e9fe953339e091042d2a..cc666de3b8e5a56b58ac984ff1f5ab890048c2e9 100644 (file)
  * 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 (file)
index 0000000..f47c645
--- /dev/null
@@ -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_ */
index a543746fb354d99913cac3323b99b6f5aa71dbc9..ad6a8b63569201050dd3a7b487c5396b6b8ed28f 100644 (file)
@@ -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;
index 2eca902a428390394af90b7d6387981fc04ea8db..3c6bbdd059a459614ab2710f377d3f9796ccd3aa 100644 (file)
@@ -125,3 +125,5 @@ static void __exit ioapic_exit(void)
 
 module_init(ioapic_init);
 module_exit(ioapic_exit);
+
+MODULE_LICENSE("GPL");
index aeccc911abb829182cbee0b82ecb4c0b49640aa2..bafd2bbcaf6541d1983fababa4563ae174837e15 100644 (file)
@@ -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);
index e5f69a43b1b18e0961ff05ddc29ae3872be962fc..b008cf86b9c3f8d4fab1493a41895f196519e94d 100644 (file)
@@ -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);
 }
 
index 1dc78c5cabf8f52175159ef6191a479828497e08..f79cbcd3944bf5e61e76a96022331a665e63f93e 100644 (file)
@@ -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;
 }
 
index 775e933c222547d14c30840daebd16b5a438be72..6e47c519c51070788ea7fa4e0a3f56896b962ab9 100644 (file)
@@ -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;
 }
 
index 68d56f02e721f8de0f3f7f7b5869168bc32e1350..05b78b16d20bdca1acb822e7654360102fb09072 100644 (file)
@@ -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,
+};
index bdf66b500f22bae2ba17dc7ed325eae5015b40ac..5cb5820fae40147a29c79913cd1ebadcbfba1348 100644 (file)
@@ -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;
 }
index e253881c42759eaeb2b76070f830de192663e347..e8518292826f0182bc23206f0b7e25fe88de858f 100644 (file)
@@ -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 */
index 94a7598eb262fec103cb9611ba8612e452d1de7b..22f840f4dda1065eb97b54da307b5f6d2dda0c5a 100644 (file)
@@ -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;
index af4e31cd3a3b6b1f895a36afaf4bb874b3e1fb66..421bbc5fee324b485f409e7a025338bc524eecf5 100644 (file)
@@ -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;
 }
index 213753b283a6838174dd1fd409add971c7a363ae..b52630b8eada26ad35f8304e436c63f3e064edd3 100644 (file)
@@ -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;
                }
        }
index ed129b4146246144de63db421ff04d28d5d7de27..b42133afca985659f6e9dde41a99ce2a05808a7b 100644 (file)
@@ -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;
index 3683f6094e3f19a3575fc29b2f55dd47250a397f..6186f03d84f37c8aa696d3df504e722a5cd36b38 100644 (file)
@@ -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);
index 22ad3ee0cf0b66c90e8663ff4e74ca3119d11730..8f7a6344e79e4ca31f7db08ac63a2d4f168649e1 100644 (file)
@@ -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;
index 513972f3ed13631f152b4d9b3bef9d8f489db857..7c0fd9252e6f03c1b1f17f53282be0c5a1fdb57d 100644 (file)
@@ -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);
+}
index 0b3037ab8b9326bd5cbbad3517ff6c1bd348542a..ab886b7ee327af413f98976382869242fcba679b 100644 (file)
@@ -117,12 +117,18 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
        loff_t start;
        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)))
index 1e808ca338f804208099472392e8a2117ebb4163..6d3591d57ea00734148e48e8fb2774bc34bb81b6 100644 (file)
@@ -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
index db542f4196a4a77f2b9e6df7f8474a7d4f2b4531..966abc6054d7b625c18a5eeb854dc065b40d43c1 100644 (file)
@@ -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);
index ffe74b27d66dc16d2aa70877397750e9d2777ae0..40c9c3eecd94560e4cc816dc1d1a2461d36616ef 100644 (file)
 
 #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))
index 9a74ef674a0e123af67286d9e0b6a560acd60420..fa6ce31c94d9c3f74eab91de2b16db361370c283 100644 (file)
 
 #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 },
        { }
 };
 
index 8ef3e85cb011ef5928e1668ea901cf1236784cbd..ef66f98e9202c28b2b13ede8fac9bd5d7d3e55bc 100644 (file)
@@ -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"
 
 /*
index 49a89397231834a67fc1436026f563fadfe57e10..b1d956d81f0c341fc8f24a8c013e3ddc1d016079 100644 (file)
@@ -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"
index b949cf85590c623610f1ada865114c3d709372f9..f1d99f4a0bc35b8b64c8e494a03c2f4049688985 100644 (file)
@@ -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/
index d0fed2c5cf2c084ec7849170f57c47cbf1e31497..a17d084117230071ad3d014e6225fd2e69f7c9f0 100644 (file)
@@ -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 (file)
index 0000000..6461b48
--- /dev/null
@@ -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 (file)
index 0000000..751488a
--- /dev/null
@@ -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 (file)
index 0000000..0491e53
--- /dev/null
@@ -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");
index 258ca596e1bcce7fc0af5229fddd7b0bfef4174a..982d16b5a846f0e1575fca4d101c91f32fa93ba4 100644 (file)
@@ -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
index ffdf712f9a67c7e725b790ff3fed54fc43985901..1ea6f1dbbedd0323fe726b1364b930befff7df0e 100644 (file)
@@ -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
index e7f301da290286153180fc5f1a9e02cdd9bb5f01..34a0c607318eb2173e4d1e44cb16aff2c889164d 100644 (file)
@@ -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;
 }
index 1c5ab0172ea282c73b0835d07be67e4172a8a6af..2b557119adad4b11d63ec345c96b425183e691f3 100644 (file)
@@ -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,
 };
 
index 67d47b59a66d878c9188afaaa62b92f255d657bb..551a22b075387a0641d37ff9dc1a34e25b65ee9d 100644 (file)
@@ -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
 
index e431eed8a8782f2f49fc1869365b76929dc52001..b802b0c7fb02d7d7bb3bf3c1fa72b95aed899ce4 100644 (file)
@@ -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
index 167c93f21981a0178a9bd9d47ba879604ed7fb4a..8b5876356db97da46cd5ac0dd59dccb4b2521361 100644 (file)
@@ -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)
index df4ad8927f0ce88257cb70db8fdfed535f8d17f2..111ec69a3e9454a40fa96091e4a7bc679cfa5dd1 100644 (file)
@@ -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)
index e3d1d063025a45b12179e0712ea0d2599bfcb21c..09014f38a9481f8afb630ce8a5c5fdb513100380 100644 (file)
@@ -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,
index f123f7e3b7525acd164ed639e022f25dc46711cf..6b981b5faa7015c53f10a463d7a53097edeab075 100644 (file)
@@ -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",
        },
index 1af97686f4448864d92b7dbfdf58e79c883edbb8..0199eeea63b13f6d770b49897d14bb3da1173290 100644 (file)
@@ -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)
index d184aa35abcb45a91795aeed9de35ad8f7d1a75a..ed7beec53af85505b49815d97d94947d0d311efb 100644 (file)
@@ -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,
index d9b1f82cc5bd80939206025432f2602072dfe244..a6d040cbf8ac1dade86099eb0a71df4c2f94c4c8 100644 (file)
@@ -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 (file)
index 0000000..2f1341d
--- /dev/null
@@ -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");
index e872c8be080ed427a2e546efffee50c12acdd9fe..0f65b246cc0c8d24c559cdeafd340232d1c55e0c 100644 (file)
@@ -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;
                }
 
@@ -1866,6 +1871,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)
index 36c5b92fe0af26487cb093234800d534061c41f6..2afa5730f324ba1ef1bb068b5f63c79e41c11a8f 100644 (file)
@@ -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)
index 27355b1199e571ed090f24c5799dce5511d2cc94..d0963090442d220f69ebecb8c6dbbf22866b62f8 100644 (file)
@@ -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 (file)
index 0000000..a4b9cb8
--- /dev/null
@@ -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");
index 359f8d18fc3f35f03f0314661aba33def33846f7..219d162b651e3c75f2077517e5b3e0b69c28100f 100644 (file)
@@ -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);
index f2e5ecdc586424ba1f92947ee5c31f1ce3268cad..261f3d2299bc0a5d2d074824211172be7a6b8448 100644 (file)
@@ -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);
index 03a1d7c11ef2b5c9ce0d07c91517673cf83d30bb..df9f42524abb3fd1164f61e7bee4065985d59d24 100644 (file)
@@ -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;
index 339f4d732e973e5c4ca543d869da368af80a90c3..9165b0c40ed32a6b4e8a851e5c81f9b1f68f8be0 100644 (file)
@@ -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,
 };
 
index 185468c4d38fcbe691c7842ca9a0f50068ca5e25..48d5b7608b00bd519cbb4c2434721335c91fa4d4 100644 (file)
@@ -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,
index 8b5944f2d7d1ddd36e82e92d786770e469743dfe..8ae288fc150b8682c9cb597b0b4c07cd8cdfda8f 100644 (file)
 #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),
        },
 };
 
index d8ecf49a5777e383876aae1f5894adc43d0bf741..d1e5bee2a26b210685290f7bb98d0a5138315a87 100644 (file)
@@ -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,
 };
 
index 7c6e3b8ff484ad03ab60fd25d07f74d80395a65f..5f68ff11a2985bb6519d0b5d4f2a8c1e89ce9e05 100644 (file)
@@ -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,
 };
 
index 3cdc755d9b225774aabf25a1101f4aeeae591cec..69c42c318b87c5506a4f1c9548bf1a303ddc3ae3 100644 (file)
@@ -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,
 };
 
index 708f4b6a17dcb02ee45b26223db11fc78b3319e3..9289ead715cab59d749c56222f605195051395db 100644 (file)
@@ -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,
 };
 
index ba3e0aa402de84a67cfcb3ac15ee8c0555f2eb1b..aef3f2b0c5ea433e45647f1c10a7a429d416a234 100644 (file)
@@ -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,
index 6796eeb47dc6f65b1997f75cacc1f04cb8e7d6cf..3792741708ce65b4b0bbb3449643baef4a21b22c 100644 (file)
@@ -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,
index f67af3c1b9638636f5bdde781d15b79d516b89e8..8c5a54f541b50964567ba739a128b0ae59ec286a 100644 (file)
@@ -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,
index 2a67d08658add7dfcabbc1c00d4a0a02b9b70a0d..b85040caaea318b13154927bc1beb0e13aef6ad4 100644 (file)
@@ -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,7 +245,39 @@ 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,                                \
@@ -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,
 };
 
index 9d540cd02dab5f4de264dc35599322b773d6c484..3ca14380f22db06aba4338544cf62967d48fa900 100644 (file)
@@ -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",
        },
index 8d531742f593616d1145fef2aa00fd22e13f4b32..4d7c635c36c2d6cc92b1ecd8fafb9d533213ae21 100644 (file)
@@ -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,
index af7607515ab951e2b688b31e0a1cffef8b8bc396..d1a77512d83e69501c2a4a3a3e8c3f09b75f7ba6 100644 (file)
@@ -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)
index 9bb0be37495f417d65728720f2d13217d51962d5..446a854455535b4603fa2584f09498b0e557cc0e 100644 (file)
@@ -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)
index 355ca7bad9d59a9583cdda44ee986ced030ab5fa..fc7935a19e3a143f996aeeb4879d4d8ba75f0e9b 100644 (file)
@@ -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 (file)
index 0000000..3ee2638
--- /dev/null
@@ -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");
index e39a0c7260dca5b7fe13098dbfd06d98c4b0b3e5..df0eafb0dc7e63a1f4a9e8bfb989d91caa1d9f63 100644 (file)
@@ -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,
 };
 
index 5dfa920ff0c8873c91e8c02176af4d722f3c3659..b821d08eb64ae84b643f2cfe93cd0764738d21c9 100644 (file)
@@ -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,
 };
 
index 0801a6d0c122e7e7b94e75b797497728ef2a7d36..c46c6705cd74538af5b30c2c112cde1cedad4df2 100644 (file)
@@ -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,
 };
 
index 1fa63812f7ace6070dcfda38a14cd5aab0466b69..0d84b1f33199ca5251c425ba898ffad4296da88f 100644 (file)
@@ -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,
 };
 
index 88cbb832d555207b4e7fc124aa05b4afcbcbb3f1..4ed89c6541100e838e8d6c3afb5aea3e0ad5bebf 100644 (file)
@@ -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)
 {
index 07aee694ba92abc4c8eab282b519a89dbff69ff1..e915629a25cf64ed660e9ac9f2b2112b1ea228e9 100644 (file)
@@ -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)
index 68777acc099fb6da2d0d4f1428b11ef1d704f9a3..4899342f1fc12cba02790a094c4be82f5ec30b15 100644 (file)
@@ -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)
index 092e5cb848a1e3b0e30736bf6fe08823220f77aa..534075e13d6dba59e5f21b4db91fb3b0d9acdb25 100644 (file)
 #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,            \
                .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)
index 8bf4e8c9de9a2a811622ff0e8986a8fea9de2735..9e6f78694bf16d66d13e9ea95e160ed631603742 100644 (file)
@@ -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)
index 926f9c8f2facde5b415b0e4bdc71b5fd2dc53fe6..bd062a2ffbe235cb9e4c4636b59b8676738676e8 100644 (file)
@@ -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,
 };
 
index abe64a32aedf3a4b38ee05ea7c59849b4959642c..9f991f2c525af531ec0b5450523bb2e0e75a5b54 100644 (file)
@@ -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 (file)
index 0000000..ab21133
--- /dev/null
@@ -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");
index 1378409efaec70170b8a3c70eeb09e1402abec33..ec9453ffb77fd561ec1c2d6c3591b7302bc16b5f 100644 (file)
@@ -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)
index 68729a7c8709fbcbc8e88e8cf99924afc2e69f18..acbd63fde4153fb7ffe9cf3a8b22dd25aad43383 100644 (file)
@@ -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,
 };
index 6998d579d07b424891a79d09e62406a6b7e38d74..9b9af6d889c83214b06e9aa6b54767ede61289b1 100644 (file)
@@ -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,
 };
 
index 07d01ccdf308fdf2a6871ce60f6d60f380d4060c..0233cfb5656058a57ccd0dce40591701c16ce8b6 100644 (file)
@@ -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)
index 001ad554ac62634c6a77897ffc9a92cf641c2abf..41c391789c9790a59678dc1232bf0938e978a47e 100644 (file)
 
 #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");
index ab00cab905b730459c6e752907f1139aaec9ee57..73dce76641265590179cb2440e75ad71ffd722d0 100644 (file)
@@ -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)
index 058d2f2675e902c8d2856b83b3ee5a6b4c7c5503..843ee0a9bb92ce2a23e7a2209590b99cfa13e76c 100644 (file)
@@ -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,
index ce1e7cb8d513f13a8463a84b2de39d1a61cb180c..f86da672c758b4ab1070facacdf291cabc482c66 100644 (file)
 #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)
index 793adda560c3c3364c2053cdb152974fc2a2f02b..59c3770fa77dbe5b77ae1b3c96c1e105cae8f58e 100644 (file)
@@ -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,
 };
 
index 18b2a1dcb4b5d6ba189fa74dfe4c8f2d23fbe1d8..17e994e47dc139c3117a8affe76eef64b5e092e1 100644 (file)
@@ -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 (file)
index 0000000..b15d711
--- /dev/null
@@ -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");
index 7eb986a4074678cb58118577544a10838b8a185a..493c8c6a241f41b1820786b993b342816002bc1c 100644 (file)
@@ -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 (file)
index 0000000..4668c7f
--- /dev/null
@@ -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");
index c038e74225381ea760f9e3984d62eb802af86814..01c66e9712a4aa236ba36ed409abbbce51cd66f2 100644 (file)
@@ -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,
index 782c228a19bd503ccda868ac67f46cce7fbba2e7..0af6898bcd79b4e2739ffaa4282f8b1aea6fee70 100644 (file)
@@ -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");
index 2646a1902b33fe6287ee4bfea055c5c0d952fba5..68586ee3e1cb18197f64ea68d7cbee9e963408fc 100644 (file)
@@ -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,
index c2dc03993dc7011d5ce9c87726cea6f25579d8c3..1ec379a9a95c88807c9987b23568e892b14bdc1a 100644 (file)
@@ -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,
index 27c746ef06364d2f02e95b8928ed748a31de6b1d..c6a32ea80b9d2aa063408f6ac38d11622253f477 100644 (file)
@@ -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,
 };
 
 /**
index 86bb48db149ed3d2bb1285f9dd4a24fb28a531f2..6ff872342648cc2cacbf23565826715b0d3bbff7 100644 (file)
@@ -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,
index e1f89d649733e22e75f1e00709b3675e9cced0a7..0d36f94ab51defdd1adea3c1d42b58366ac02f21 100644 (file)
@@ -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;
        }
 
index 26c81f233606ebe043360cf349196f5ed7557670..afb7cfa85ccc04ac637268ee0bba4240f05c12d3 100644 (file)
@@ -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)
 {
index 77823d21d31488065b6ca8a12de02d1b5e9f013f..a7a2a998fa91fd2b626b2a241dbeef7ff212341e 100644 (file)
@@ -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
         */
index b2b8c18eecedc98f32b708aa000649f35102fa93..20cfd028edcfae886f44584289295c20372aa5d6 100644 (file)
@@ -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)
index a0a4afe537d079038e02b74e7606b66b0cedcee4..5c70a6599578d6940faff2e1791e89ef4d4b769b 100644 (file)
@@ -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);
index 98ea9cc6f1aaba9f442ecb4b46724c0f3f5ccd7b..817b68925dddbd5c097129e6da6be7f41c77bdc8 100644 (file)
@@ -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);
index 05b734a2b5b7ae09f33f2a7307948e232e4f253f..2dbc77b5137bacb4e3d283ed6b0eea4fa45c8395 100644 (file)
@@ -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];
index fa7adad6f9ba07f6e1948d775898866fbfe9d019..480fbeab0256ab3406feffd0dd93a2b70dc666c8 100644 (file)
@@ -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);
index 4d6ba00d00472055f56afe7ad2b4f651d7f6fe26..638a57f4d8a11cc1ad040914f7991f2a780fefd9 100644 (file)
@@ -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},
index fddb62654b6a6cabeaf4e168951a305cddce1abd..73195553f84b168442918a0c6697d9ef090999c2 100644 (file)
@@ -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;
index 5ba390658498afb4b0b0b583b8ee371aea8863de..6e5eef01e66784b4eaa3e9357d81c7e89b96e47e 100644 (file)
@@ -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 */
 }
 
index 6d6eee42ac7d4181c775c5617475720c4e50c231..ef60afa94d0e75c265a5010be1dc72c62b82166b 100644 (file)
@@ -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 */
index efc6e72f09f34fefdf6faa947bdf74ab588f2a5d..aec2e0da50164ca688cc9e2ea95355f0aeaf4669 100644 (file)
@@ -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
index 5733811ce8e79eb0bce599550604fe6290444f5f..9d1c7b56090a950a3777e5c3244b265167d647cb 100644 (file)
@@ -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;
 
index 14cd361742fa668259b1df795bec4616e7bd68d4..f5e297c6b6848e2ef9d8940107c8a0b245e54e28 100644 (file)
@@ -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 */
index 62aa5584f64478d286e373414dd8b119315a5204..b49d21779a2433ea653ccc6c40fde97527ee1289 100644 (file)
@@ -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]));
index 3d74f2f39ae18954ac825f4599b689d770f494cf..4372e32bc95f71bfde3adf95d5c5ebdfbbfc8c9b 100644 (file)
@@ -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;
        }
 
index 266aa1648a020e0ce36df5d63795fd4706869ef4..19396dc4ee47f947f569a26308416f99401acb21 100644 (file)
@@ -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);
index e9d2ca11283b3e60fd8d63a31bf59b739135739e..95c33a05f434afda124a9b04300906d5ee9d15e2 100644 (file)
@@ -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. */
index b58fef780ea063827f6bf5d66aa10547f17c9edf..a43415a7fbedfa7dd537d2dc48581904adbb3db9 100644 (file)
@@ -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;
index dc47f30e9cf7c1be458291ba0d9691bc7768e569..553227a3062dfa739fd6868990dc4a70118ca045 100644 (file)
@@ -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)
index c6250867a95d4cb0de8ec92e498b995aaf84d99f..5bd05b136d22ef80b2cd93f78b65d6ef60640473 100644 (file)
@@ -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 */
index 9ef124f9ee2d4e73f20db392e45b29b7c558ec00..bb18d76f9f2c39668dc0fa80ed854aa16fbece7d 100644 (file)
@@ -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;
index df0f145c22fc80c175d277cca0f68647fbfd90fd..6e0daaa0e04ba6b01417d7873c8dde129fe1883f 100644 (file)
@@ -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);
 }
index a305550b4b65ecce6c5e6e925c63c36667edd3b0..8942db1d855af8ef69c6f3f4d639f4efe414fdd1 100644 (file)
@@ -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_ */
index 78f3a2e013c4c3881894749f259e89c5ecd109cc..17b45ebb0553aeabb4ac0facf47d7a4b029719e4 100644 (file)
@@ -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
index 294e9b40f51666396c2a56c3d92036951e04382d..737f4a9d86a33fb7fcb865c11f43453d15bd7ecd 100644 (file)
@@ -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;
                }
index ff6fd4fb624d44fc4791a62af7e837ba18c10fc1..0f03b7919d7c2d13b18221cac4e77cb962f195da 100644 (file)
@@ -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/
         *
         */
index 8aacf611b86d43243677845c0a89b8abe825f5a0..8e6298cc8839711e03745c08f7be04446ac47f3b 100644 (file)
@@ -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);
index 90b740048f26ee7151eda956b092e12fad74e70c..1bf7432bfcbc659f8b27dc15400016b31173add3 100644 (file)
@@ -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");
                }
index 1a91195ab619a9ebbfa503cf7851c3cb8ca02b49..69e0cfd988704a9f18143d3231d9c2fb79daaf29 100644 (file)
@@ -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) {
index 8636fae1f7ecfa88909b5b4aa7eb39b71722933f..c2c77d1ac499d3ccb4d4c141d66986e88e980bf6 100644 (file)
@@ -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
index be1a9a1e749e6761678fe1c135a1a64ff25160e7..cd69b48f6dfd390a8231f689b35f5d2588c16772 100644 (file)
@@ -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;
        }
index ed6f5f1f5a552e461af7ddb2941774194ea2c558..0c629807610e6576ff822f2b958d8894e4182dc7 100644 (file)
@@ -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;
        }
 
index 9d6bcc77c73ca4fc253411557fb413082e2822ef..002c34e72521097525d478577fb2737b2faf7c0c 100644 (file)
@@ -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;
index f3d283f2e3aa280598867500de23f142cb050670..c31133a6ea8e0361f1f84103c469026bda82c077 100644 (file)
@@ -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
index e6a008f4939f47ac6aac0129ef0f1cf5b90c3998..2e2b2c1cb72252d607dd747305cb354c68dd2cb7 100644 (file)
@@ -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__);
        }
 
index 6197a69adb4d407e3011c37625cbca8faae66eb1..72b6334bcf1aacae37068258ec9d4cbd46e6bf3d 100644 (file)
@@ -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)
index 88dde95b6795fcc66cf7016cc2ff1559b633d0f1..d938b2b99e31fcee332a2f83ae46e4998907190a 100644 (file)
@@ -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);
index 59dcea2f69574f9d62747b315c141201e130de1f..f4a21f6f081f280ea117860a46e0ec0bf13f573a 100644 (file)
@@ -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.)
  *
index 09699f6e87f8df51e30bfb15dacbd73283312bf4..8bfe990caf1ac40f23709016194686b008270471 100644 (file)
@@ -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>
 
index f74794c93152ce15ef52db05b090a477cb0c090d..a7d1f5b4c4eda4446d0fac523f72b7e068852d06 100644 (file)
@@ -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),
+       },
 };
index 9716850a430919b894d73a9cefc56e02b8b18a36..98df17c984a898bee7786f8e07e6421a626f2a7c 100644 (file)
@@ -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"
index ea5f2586fbdd3f9b8279c2d7230a2dbe5f067334..6c3586a4c95635780cc4adf7a8f14ed62cda6b24 100644 (file)
@@ -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);
index 7f93f34b7f913e188aa31fbe82372f409817e9dd..ebd08b21b23432696047487367d44f76d4fa4f02 100644 (file)
 
 #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;
        }
index aa31692064ddd08b6aa91718ed1ece369da74631..d670130ee687e803407a10075608bb883ab70451 100644 (file)
@@ -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;
        }
index dedaf81d8f36fd89a5258d9a21fd261401f6e0d9..34389f75fe65693a4ad5baa36715159fd5759bbb 100644 (file)
 #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);
-}
index 1125af3d27d12b3f724a79a259aa774e6d214b67..2639c58b23ab497ace850895f3322df661a965df 100644 (file)
@@ -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__);       \
index c39d6e46f8c52796d113076ee9b3532890b7a814..b52f62595f65a58ac39a652e66df741f82dc8011 100644 (file)
@@ -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>
 
index 1b5ee8ec192ac35a0d7843402a554d3a0643fc0f..e31f5b33b501e155fed50e9a5463614e9cdc1690 100644 (file)
@@ -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"
index c510a445739818827cd5d8a51b143956e6f45eb4..d4e7684e7045d5f58c863572ff5341a2c9f36479 100644 (file)
@@ -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"
index 05e1be85fdeeda07a21651ee1a4096bf6b77c06d..dc42e44b6bc1130516f67554ee6ff1675d8f739c 100644 (file)
@@ -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),
        },
 };
 
index 5b06d31ab6a98678320b8c88456f0d3abde2cb35..c0bc92d8e438f40a1dba75e078a636fb56c7b99f 100644 (file)
@@ -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)
index 43cc1a1e25d4be3c0c5fdfa1ddec4bc7107a42d9..3e3ebbc83fafe8ba194470c0da8d9fe862897684 100644 (file)
@@ -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"
index 961d664e2d2faacde4272fa83023919c6ebcf3ca..68dcc59cd28783bad5a62e97a272bd31114bca0b 100644 (file)
@@ -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);
        }
index c72ead869507412ac9939c0748a482035baaf2aa..596617ecd3296e22eebb4bb08ec57cf4170a100e 100644 (file)
@@ -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;
index 3d3e2c17d8d12234a4a5fdcf2fc1af0eb717b6dd..06b2635073f37dbd15969803f4387020344f26ec 100644 (file)
@@ -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
index b8cbc8d5c7f7cb39ed770fb2b256427f25bb9c69..ce9f79216723fbfcfc563d17e5e8974cbd2e9b00 100644 (file)
@@ -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
index dd27a0b46a37d1dfd878828672dfb0dbe99f5ac8..853fc7beedfaae7fd7ed03750e786693839b3f47 100644 (file)
@@ -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. */
 
index 0f5ebb72a5ea01693b339d66e3f928de9b783f78..e3c6ee3cc2ba3904cd623433a136f78fe2f3ada6 100644 (file)
@@ -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);
index 22ab7b5b8da7eda6bf38d19aff3415eade104c5c..2d5622f60e1121aafc4dc96bcea96cf491180d9e 100644 (file)
@@ -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
index 3c20de1d59d0d44586199ade586864758e2ce204..df163da388c9ccfe82348c51be596c9fcfd8cc55 100644 (file)
@@ -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
  */
index f775bfdd6e4a7f3e0700b8ea556261ad8c13e3ba..cccdc874bb55df99eb10f89f33a7bcb1f92ddc99 100644 (file)
@@ -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 */
index 4a55f35a6cedb81cb0f7ce81893d57fa10d0a4b8..78bde32ea9518d3fffe72d24864b6959bb369781 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * hugetlbpage-backed filesystem.  Based on ramfs.
  *
- * William Irwin, 2002
+ * Nadia Yvette Chambers, 2002
  *
  * Copyright (C) 2002 Linus Torvalds.
  */
index 7f5120bf0ec29cff214cc8ccb2a23bfb02ad3419..071d6905f0dd92c57dc2a8e6a5e62f81993ca5e8 100644 (file)
@@ -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;
 
        /*
index a74ba46595499690186dc2a46eff5160550032ae..d8da40e99d84b7f3de4471603dd51dc7e26b7f1b 100644 (file)
@@ -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;
 
        /*
index adb90116d36b1b2b0f0328a58cae9cdf0dde1794..af49e2d6941a7c2f8120ee3ca99095e0bb2ea767 100644 (file)
@@ -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.
  *
index be20a7e171a0f18ebe24d32d0ebed2b4d71a6040..63d14a99483d5d39ec58bfd8419c53173721da99 100644 (file)
@@ -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);
index 7dceff005a6745eb353187c93b6e11fa3b326cdd..e5f911bd80d2488689966cfd9cddf704fae07aa2 100644 (file)
@@ -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.
index c887b1378f7ed5087eca0df3ca745e15d9a88cc6..48cb994e4922cf0d32fb3f61ad1eb05291231a7c 100644 (file)
@@ -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
index a781bdf0669464ced3e213faad5ed6ab3a37a06b..701580ddfcc3c20a4476fe88a9e736b54ca7b858 100644 (file)
@@ -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;
index bb145e4b935e79760146f17d5f6bd4c70843278d..8b1d7a6a9695c44582890dc2a89acdd0e709e7b4 100644 (file)
@@ -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) */
 
index 6e3f54f37844af0475611eda1d0a1fb754117b04..fcdd81bd531493645930cf2d2e19661f4ed63f0f 100644 (file)
@@ -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;
 
index 22ef21c33d0c600f5adf48d34e5bdde4687d76c4..c1da539f5e28a965702c39d21375923e8271f67f 100644 (file)
@@ -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;
index 4eb31752e2b77592e8a2fdbf3fde779d4851504d..deb0ae58b99bb3724bee4376b0a376b563c29cff 100644 (file)
@@ -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 (file)
index 0000000..e5dfc25
--- /dev/null
@@ -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_ */
index 4180eb78d5752de3d16c3f836359039af09737e8..93b1e091b1e92460cf473308c8a7ea953b2d493f 100644 (file)
@@ -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;
 
index 1cf1749440ac66dabd8b0f797e80690bbde9961d..e51359180b6f7c6bdd85bdd33c86eb6792301ca7 100644 (file)
@@ -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);
index c0043645cdcb0f8f4cf4ab04de7f22c438336b98..0baf8a56b7947b7300e5bb2b1b0a8dd5ef188483 100644 (file)
@@ -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);
index 6c9cb93ae3de4bb3210f5037dbd3865fe18288d3..7e8104bb7a7eb11f412fb504df6552e6595ef40b 100644 (file)
@@ -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_ */
similarity index 78%
rename from arch/arm/mach-vt8500/include/mach/irqs.h
rename to include/linux/clk/zynq.h
index a129fd1222fb465acdc5c299d0ac1b9fd9924a48..56be7cd9aa8be535b8bca9a604e1a96444f69867 100644 (file)
@@ -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
index 1d47dcce11e1011e8a39a96b1c5fa10d0eb7bbca..d02da2c6fc1a615a1d2c3223a3c19c4686fea3bd 100644 (file)
@@ -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
index c47ec36f3f39cc71e53420e9e9433b181780f680..b02099d0b4fc20020dc578257983e804859876b2 100644 (file)
@@ -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
  */
index b006ba0a9f4269e79d8bfae11415e8b3c8785f69..243eea1e33d8021b685f46a736e726c74e083a22 100644 (file)
@@ -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
index 24d251f3bab0711c26231d67352df1ca140e608a..c45eabc135e1f00b7825d017b37df1666acb203e 100644 (file)
@@ -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__ */
index 24df9e70406ffb94fb98faf91c174e236155a639..61c97ae22e01881d7e1744401e52705c7986fb99 100644 (file)
@@ -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
index 1fb26448faa9ccb2a7ca85c9dcca74d52413f87c..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1 +0,0 @@
-header-y += ioctl.h
index ca8d7e94eb3cfe59d6baf497d47423d2feb86248..55f277372fed00e6b454d9fd7249bd531ccbbb8d 100644 (file)
@@ -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) */
index c076041a069e88ee700e12d1bf5d3ca4b6f0a2eb..7330a0fef0c073b41a409882145eb36add87dc02 100644 (file)
@@ -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 (file)
index 0000000..60e411d
--- /dev/null
@@ -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 */
index 2385119f8bb016c003f5bf2b638b412a6ddde7f9..f0859cc73861720a982c185a3422fe66efbe5415 100644 (file)
 
 #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
@@ -665,6 +667,21 @@ struct ieee80211_meshconf_ie {
        u8 meshconf_cap;
 } __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
  *
@@ -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,
 
index 1cc595a67cc900b18afe694ca712700fba7e5c2e..f4e56ecd0b1ab49b0e09594e16fe996165168d11 100644 (file)
@@ -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_ */
index d032780d0ce50849c5441aae24025b2cc2f80cc3..a9d828976a77a56b400ffd3f4e7a56915f3762a5 100644 (file)
@@ -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)
 {
index cc5cca774bab14590e544f682c96a4ab72cd89c4..2e86bd0bfba11cbc6263ba8942ddbe4ca0760701 100644 (file)
@@ -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);
index 58b82a22a52b90288566eaa36e9d2bf8095a363c..492bc6513533cf8d09fdfe667711ab0b78c3a0d2 100644 (file)
@@ -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);
index fcb5d44ea6358b8165a2a1b80ddca56fb3d80595..8ea3fe0b97598428723615c13a042145685adb99 100644 (file)
@@ -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.
  */
index bcba48a97868e9b38d6a92f38e5175b2474df330..faed1e357dd6c605cdea3445a803e167d17d3e0c 100644 (file)
@@ -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 */
index 06177ba10a1617461dbe6803efc22ba6dfb43304..e83512f63df550a64cba3fb74c51c5c3b5dc9030 100644 (file)
@@ -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);
index 7a71ffad037c7ebd07aa79d7e23c08b6b38554bb..cafc7f99e124ec0c5a39743f048527a9875a3b55 100644 (file)
@@ -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.
 
index dd231ac0bb1fd8ac678d475404bc95ebaa104cec..a580363a7d29723e6656cbed8d9d94b4b1801bea 100644 (file)
@@ -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);
index 7ab442905a57b209b10c042cf141ac2b2ba2275e..8b1d1daaae16c27e59d037f46899a1f6c631acc4 100644 (file)
@@ -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
index 7671a287dfee4f592e909c15bcc0c14cac47bb7a..ba26e99c388d0a7f6105ce9181cdc0f94e42736a 100644 (file)
@@ -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
 #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
 #define ARIZONA_SAMPLE_RATE_DETECT_D_SHIFT            0  /* SAMPLE_RATE_DETECT_D - [4:0] */
 #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_LDO1_ENA_SHIFT                        0  /* LDO1_ENA */
 #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
  */
index 147293b4471d6811248388c3932e89e65a3b844b..f87a6c172a917f860976e90a62ddd8c790e4266e 100644 (file)
@@ -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 */
index 830152cfae339727ad1d70875a61dbdaa34a6c67..6ae21bf47d644fe8424587b31afd880701720434 100644 (file)
@@ -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 */
index 328d8e24b533acaf524746d01dbf1cba76656782..1d4a4fe6ac33e9341f8b90bb0a0f32a015b490b5 100644 (file)
@@ -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 {
index 6bc31d854626b26f62994f0810a143ee00027e17..804e280c1e1d9a2a18157b377bfef9f622834cc7 100644 (file)
 
 #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];
 };
 
 /*
index 2dd123194958afe1551c63d30cc16dc200410f1e..f8da0e152567059e0d0928c844e70dda7a94cc4a 100644 (file)
@@ -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];
 };
 
 /*
index 1f173306bf0508ddeb3a18de8175fac44c857ee3..ae5c249530b4e7f527a22f44e242d4d4bce66419 100644 (file)
@@ -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;
index fc87be4fdc2501a8106b18664102c793ccdb588b..8e21a094836d21566bec6f08c027ad5c765fa715 100644 (file)
@@ -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.
         */
index de201203bc7c833a09651f75678b833cfac0b880..adfe8c058f298ffb4f619688676423ea67838997 100644 (file)
@@ -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
index a848ffc327f4f19e3b1da926f52aa361fd27b654..02e0f6b156c3f2dc7c2cae5c663cbdbfd6341484 100644 (file)
@@ -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)
index 5f84c6229dc619e65ed0ec4a9dc65187c3daccf0..610208b18c05819dc4cfecc0554574269157f90f 100644 (file)
@@ -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 (file)
index 9890bba..0000000
+++ /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_ */
index eb475a8ea25b91ad776dbbfeeb3ea085b2167f1d..7af25a9c9c5172b92a31e3626901971521530398 100644 (file)
@@ -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 */
index eb1efa54fe842186893e1080e63a8db64f63098f..d42e174bd0c85860de4521c0c67df289c7e4489e 100644 (file)
@@ -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
 };
 
index d03d2463efac286a3a70186d69a1fca78bfec5a6..15472d691ee68c6aad5dbeb0a75933ec18f00404 100644 (file)
@@ -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;
@@ -603,6 +609,20 @@ struct pci_driver {
        .vendor = (vend), .device = (dev), \
        .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
@@ -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)
index aa9875f77c40489527279342ca8b1d1da89866c4..88272591a8951d09fb18d8b7967ed3e885ca8855 100644 (file)
@@ -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;
 };
 
similarity index 71%
rename from arch/arm/plat-nomadik/include/plat/mtu.h
rename to include/linux/platform_data/clocksource-nomadik-mtu.h
index 582641f3dc01acf611f34edb846f741ded736d8c..80088973b73486c0f4b129b55b3a85b2bad8bea9 100644 (file)
@@ -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);
 
index c4e23d0294987a64a3fbc6202df4bb3dbe6f8ff5..24368a2e8b8713dcd9678dfa9045834b8d00f465 100644 (file)
@@ -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 */
 };
 
index 5b2d0817e26a106e643605c062f01231652ac7c3..94df96d9a3362609cee973227e6ddceef42cba2b 100644 (file)
@@ -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;
index d0c5825876f8a2d1d124a3d51fac880951a63b2f..8db5ae03b6e3f679c16988e492e8241f1567b2f5 100644 (file)
 #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,
index b081c7245ec8a94cd7ed3664c1f91a0e15814897..044a124bfbbc6b313d96f187a598fcb1438b8cc6 100644 (file)
@@ -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__ */
index c7bef788daabd14735d053e5c8ad680b247e11f1..ee60ef79d79270262bfb1992f4f7695f422323fc 100644 (file)
 #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 (file)
index 0000000..713bfd7
--- /dev/null
@@ -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_ */
index 4a496ebc7d733c69432896ec08cdce5a0ba89964..c0f44c2b006da4ae05e4c55e7ed322fb50c581fd 100644 (file)
@@ -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;
index c43cd3556b1f5b789bae79de586f7e85a4cafacc..7bc732ce6e50c5793f3db777d07a2ced422f91ef 100644 (file)
@@ -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
index 7932a3bf21bdba89f84275b7b990bcaa3a5773b0..d10bb0f39c5e72fd6bb7747e47761d062f75c981 100644 (file)
@@ -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 (file)
index 0000000..f8acc05
--- /dev/null
@@ -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 (file)
index 0000000..d00841e
--- /dev/null
@@ -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 (file)
index 0fa04b6..0000000
+++ /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 */
index 7002bbfd5d4a55e76041e146cd268a9d027ed6ed..489dd7bb28ecf2920e545bf65cdb29d64aab9bdd 100644 (file)
@@ -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 */
index 6a2c34e6d962658d0a1532959a06b5ddebe65087..320e976d5ab861b9e143476ae7dcd4b87956854e 100644 (file)
@@ -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);
index ce718cbce435f4ca2a52e1bac32b60631455bce0..f4bf16e16e166fce6ea13bb92b759a00d48f0ecb 100644 (file)
@@ -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__ */
index bb674c02f3060c3917763dfe2bae1f8bd3559a4d..1f64e3f1f22b52f5d1db2f57bfb69c4a80bca0e8 100644 (file)
@@ -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. */
index c2b02a5c86ae0bb03798d9221c6199dc8be63d4b..38339fd68a5f101ee34393fab98ccfe7db2b0886 100644 (file)
@@ -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);
 
index 91161f0aa22bb874aa928943fcbdd6f74f65eda6..99511d0e931d717dca4cabae0e70be102179e19f 100644 (file)
 /* 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_ */
index 5f44e9740cd2a3453da6767778911fb3aa59eab1..07a9c7a2e088e5baedd31426a1679dab23def26c 100644 (file)
@@ -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);
index a0525019e1d1b9fdb703ed4ad1483b878ff0ee55..6ecfa02ddbac9e4917725938efca0ca37b07da64 100644 (file)
 #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
index a1547ea3920d226cf56286b119c0e72d7a5b8712..c1b3ed3fb78715fbe868ab531d07e20b00fc05cd 100644 (file)
@@ -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);
index cd844a6a8d5f9f766503f91d229694918cbe14fc..14a8ff2de11e54907ff63d20ee23c7d4c29896fa 100644 (file)
@@ -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 */
index 60b7aac15e0e436b9b6451321d421a286fa9a40b..4e1d2283e3ccfda3f754229d7272e540c086d139 100644 (file)
@@ -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 (file)
index 546e223..0000000
+++ /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 */
index 0b67d77935204b2ae7dab682270cc30a1b1da6d6..9d81de123c9017f4463ba4fa09a61b8b7425a8bf 100644 (file)
@@ -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 (file)
index 0000000..3b8f9d4
--- /dev/null
@@ -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);
index ddbbb7de894b4039d70003197737d5591649ad15..9bbeabf66c54d59cede412db6084c1e4315f2d48 100644 (file)
@@ -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
index 0ee42d9acdc0f605dc0264b071834cb53dcd95e9..2c02f3a8d2ba3f4ba079a51f537be25742b17162 100644 (file)
@@ -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.
index b7f45d48b2de6b4a81dcad34dd13ecc6e68443db..87490ac4bd87c72909aa8171e12ec8381af54f8c 100644 (file)
@@ -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);
index 9e63e76b20e7e0ce4b60aa5daf0e113b6985ae16..df4ef945338425d7fc6d64a858dd706d2628ea28 100644 (file)
@@ -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
index b5f8988e42837b6d703783f6f94dd6b9e4b09cba..0a996a3517edd2e652bb389ca4093d9928e7b974 100644 (file)
@@ -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;
index 6a76e0a0705eff9926c3558c3120f6cfab71eb71..42f21766c538b4bfeab6d140aaaa0fcada8e1f16 100644 (file)
 
 #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 (file)
index 0000000..7ea3db7
--- /dev/null
@@ -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 */
index ede036977ae8b6debe3ee4560f7e93905bd92f9a..2554b3f5222ae0fa32b7f6fce650fb65327a65db 100644 (file)
@@ -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 */
 
index 76b2b6bdcf36a281d558925a2a7a707ca2e1dddf..45eee08157bb926b316519da7cbba8cae49d2e71 100644 (file)
@@ -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;
index e7d454609881a30d929ec8aa613390df157c8b43..014a2eaa53899d40e1d1eb91f54ba3870e09e9f4 100644 (file)
@@ -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);
        }
index 7ed8e356425a16dc33c5afd5e4a80eaafdd6ea64..7588ef44ebaf22e7cc76a55a40a77166325791d0 100644 (file)
 /* 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 */
index 7d5b6000378bbbdaf8a4fe7316ab93786429cf3a..8e6a6b73b9c9ecc3f8f221c4ff32a9983940dde4 100644 (file)
@@ -58,6 +58,8 @@
  * structures here describe these capabilities in detail.
  */
 
+struct wiphy;
+
 /*
  * wireless hardware capability structures
  */
@@ -305,6 +307,104 @@ struct key_params {
        u32 cipher;
 };
 
+/**
+ * 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
  *
@@ -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];
@@ -1086,6 +1205,18 @@ enum cfg80211_signal_type {
        CFG80211_SIGNAL_TYPE_UNSPEC,
 };
 
+/**
+ * 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
  *
@@ -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 */
index b6a6eeb3905f15d956fd1190cf6c415508cea0bf..2581638f4a3d6ac803d156ec4dd333eaf1a0cdc6 100644 (file)
@@ -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)
 {
 }
 
index 4fd8a4b4b7eeee98198c2e999d2a72951d95f8fa..e5062c955ea6594c3d7bd7850b76bce6a3640b5a 100644 (file)
@@ -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;
 }
 
index 7f0df133d1197cf7c449d841d9ea81a5f3a07d70..c3999632e616189a81d257dfd68a16ee80f3ce3b 100644 (file)
@@ -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)
 {
index 54be0287eb982cb55f7d26973ae7aa281de8a72c..67a8fa098e3a2b0d456996f78af4ff845db4d079 100644 (file)
@@ -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 */
 
 /*
index 256c1ed2d69afc06cfbc8b51550c7b374a166afe..a4196cbc84eca774d45a2d275f4a38eb5be775f3 100644 (file)
@@ -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;
 };
index ba52c830a7a54569795dcd30a32813e1dc580a75..7d658d5773681347bb3e799990dd9947c73e8e32 100644 (file)
@@ -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,
index bc1b0fda2b0452d7cadd32a30f6df0e2a697d99e..652d3d309357c8d587c313817c61261479c78e0e 100644 (file)
@@ -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
index 8a2a203eb15d087c4838e80aa52e55208cbee1d5..fdc48a94a063ae8ce746c501a477ab3471ab028e 100644 (file)
@@ -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;
index 5fa2af00634a4c52131d17b57639eb2358dd82c8..27d83183e615ef0029150d58858e7828a06e6921 100644 (file)
@@ -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;
index ee75ccdf5188cbf4eac840714a22b456d6700ad6..68c69d54d39281ee033d765a1b9b66567c55d06f 100644 (file)
 #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
index ddc077c51f324d74e248fada33fd152238cf5337..21947cf4fa4678f5cb301ec29ddb65b74492a6d6 100644 (file)
@@ -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
index 979bf6c131412be9a4662d4738056feb91a26272..5af66b26ebdd6379ce34ae1a914c3c71a2ce5f32 100644 (file)
@@ -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,
index fff11b7fe8a44c67e6641bcc39a48fb3278012da..591f78631f137f7a235e7dea3768ba6bbca47f61 100644 (file)
@@ -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 */
index 82558c8decf86e7cf720d6b7a190455c31e60be3..ee50c5eba50c027aed710c7fded8616b9461b96a 100644 (file)
@@ -143,6 +143,39 @@ struct ieee80211_low_level_stats {
        unsigned int dot11RTSSuccessCount;
 };
 
+/**
+ * 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
  *
@@ -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
@@ -3144,6 +3330,19 @@ void ieee80211_get_tkip_rx_p1k(struct ieee80211_key_conf *keyconf,
 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
  *
@@ -3293,6 +3492,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
  *
@@ -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),
@@ -3523,6 +3741,27 @@ void ieee80211_iter_keys(struct ieee80211_hw *hw,
                                      void *data),
                         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().
index 980d263765cf41059ede684d54abafb6a9e66c6c..7af1ea893038fd211af63298c13a92f8a0107877 100644 (file)
@@ -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
index 95e646641184a3cdd2b32255822490683ea4f819..c5a43f56b79690104c94811bfa8f83719bf1aaab 100644 (file)
@@ -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;
index f1494feba79fa966b6924287f6cc095b893118ae..caca0c4d6b4bf4c606438df0a3de24369ffb4738 100644 (file)
@@ -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);
 
index bd8eea720f2ed0c3e0b61de6b03cb36035ff61cf..ad14a799fd2e50b153e47e80a9cd6fbc4235be7f 100644 (file)
@@ -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
index 252fd1010b77c090766eab54ff02dd60197edc1b..fb1c0be38b6d4332b6bb5645efde17c68052342f 100644 (file)
@@ -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 */
index 5e5eb1f9f14b8ca58f222c8397d6a403e3e2d8df..3573a81815ad9e0efb6ceb721eb066d3726419f0 100644 (file)
@@ -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;
 
index e900072950cb8cf5635e4a106389e34bd5df21f1..671953e11575449b30a10081d5b7aa7b26c0fa0a 100644 (file)
 
 #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 */
index f05b10682c9d9bbe0aa65579fc73bd8adf1747df..fce80b2f9be7e5eaf50e5fc5ccf55fde0440f793 100644 (file)
@@ -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;
index 929528c73fe8454a1dd34da7efbbc6d1fd8677fd..047c0476c0a095c2b271713ca232f7099564558b 100644 (file)
 #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 */
index b01d8dd9ee7ce99eb1bf702f00007ae456f28c16..a51dbd17c2de0cede7d134667e641477030519b0 100644 (file)
@@ -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];
 
index bc40b633a5c4dc0e763c5c8c4ff123135160dc04..2ea40c1b5e009746dacb8f146fdcc37309aa7ff3 100644 (file)
@@ -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)
index 6b00c4fc4291f1704e439e4a5db217b6f0a3db2d..5a15fabd6a750eb2fca1e832285a5de0179a5085 100644 (file)
@@ -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);
index 4616f468d5995f9a0b46d7351c5c8f7dc3a869c8..1540f9c2fcf4b555780087e48850911659009c25 100644 (file)
@@ -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;
index 712b3bebeda78dbb2d3dbb2387fd15f3dd6b82ac..35247271e5571153110fa7759e6c24c13c1114aa 100644 (file)
@@ -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;
index d053d2e9987613cea680ea433c3e3ae54b2906cf..c29707d654c065c3b7470166c6318e06137580e6 100644 (file)
@@ -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.
  */
index 9c6414f553f91f2256698323ea5d8ec72db4e868..7fdf298a47efc1d18794661b652598cf960c7df2 100644 (file)
@@ -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
index b5887e1677e4e421479919399b945844133595af..2a82d1384706c61a6757db53edf8d81a53cbc7de 100644 (file)
@@ -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 *,
index 64158aa1bb5f604aad0a68b172c2a1a674acca38..fdeb85a970fc846f81f53798129d12446f0318a4 100644 (file)
@@ -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;
 };
 
 
index 2e5ee0d8458d929b284bd1b510dcfbeac1ff4aa3..ff1b8ba73ab10b5678562919e6c43db0f768821b 100644 (file)
@@ -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);
index 1b02d7ad453ba9cd0de1e566cd5220bf4333944e..9a0ae091366da42599e0a21dfc66e6fbf4e136ca 100644 (file)
@@ -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 {
index c945fba4f54351475ff2efb989f77b23237f60d4..93a6745bfdb2bb14933018a9bbc497e6b1c0cde7 100644 (file)
@@ -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)
index 4af45e33105db2ee37b8ca66d6ec4122aa487456..aed42c7851539ba945c562e7de8692e1201eee7c 100644 (file)
@@ -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);
index 6df30ed1581c5b750f13335a3fd1b1743e05159e..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -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
index 1505e6d5ef8241081c24c74b6218e01a37afc8d2..75935ce739c555109feeadf97347d5beb75528a0 100644 (file)
 #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 */
index dfe7d441748c208501d0cc3c3806ba293da9b862..c2dff5369d339d07f181ab5fd75887e976cfffb0 100644 (file)
  *   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>
 #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 */
index 50a059e7d11616d4eb836cf7f0cc738cc0eaed3f..6d9e15ed1dcf0cb2875a10ca6795b14f3d4e0c51 100644 (file)
@@ -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 */
index 1a33f48ebe7875f6ae6b6769583646a2e501dae9..f841ba4bacb81985f1a52257c8230a22de0333e2 100644 (file)
@@ -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>
 #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 */
index 6268a4192d5c4a3300a5792ceb08610386b9256d..45c1981c9ca2b67fa7fb5ce76f609a87bc5a08a4 100644 (file)
@@ -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 */
index 7e950560e5912dc8e1b20dc58b31c795fb94d6e5..c7c7788005e460bd8c41615ae5f86f4854839349 100644 (file)
@@ -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>
  *   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 */
index 906010344dd7e0a227449f674d64b00a07dc1e86..cc1c919c64365898c47f7f6871b906dce0e5e1d4 100644 (file)
@@ -26,6 +26,7 @@
  * A:  inversion
  * B:  format mode
  * C:  chip specific
+ * D:  clock selecter if master mode
  */
 
 /* A: clock inversion */
 #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
  *
index c009f70b40293a70fa4b54afeb8fb4b879cac449..24e5d991f148be2d8b16cc309e1af7dca5f5f14b 100644 (file)
@@ -26,6 +26,7 @@ struct aic32x4_pdata {
        u32 power_cfg;
        u32 micpga_routing;
        bool swapdacs;
+       int rstn_gpio;
 };
 
 #endif
index 4f67c762cd744fae8380cec92f1a0b8a83ac2119..f634f8f85db53addf02c5f9e85d94363aee23de6 100644 (file)
 #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;
 
index b1bea03274d5dd0ca36d31e90b361d0dc63225ec..2d32d073a6f9e4275d47c27cbd63b169a3267b9a 100644 (file)
@@ -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
index 19e765fbfef716442b38f1bc89eb7490c08c0c76..4e67194fd2c3c669a3be0f0a6965da816b36457c 100644 (file)
@@ -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
index d3eaaaf1009e6a42618351b8f2844fa75d4f8e66..be8c41e2dc1589f8e899dee0642418f76628a551 100644 (file)
@@ -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)
index 3d7922433abad7b6e3cf7985897e9536eda49037..9cfde6941099635ee567d28e240f8cbc02386f51 100644 (file)
@@ -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)
 
index aafaa5aa54d46bb9a93a8137a22344408298223f..8c1d2cb75e330ae605277aa70ec44415a53f3428 100644 (file)
@@ -1 +1,2 @@
 # UAPI Header export list
+header-y += ioctl.h
similarity index 96%
rename from include/linux/hdlc/ioctl.h
rename to include/uapi/linux/hdlc/ioctl.h
index 583972364357764ec38d4ef91a95b080ed808659..04bc0274a1898936fc19fedf6f282a4da8606709 100644 (file)
 #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__ */
index a8fe9549ddbc65f068bcb992cc16f4a734428b27..afbb18a0227cb2673cd1c23f8c0b94d561af4c54 100644 (file)
@@ -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 */
index 0343e1f0582c01bcd54425bbb551098951d3767b..67fb87ca10945fda5711cbfe4cfc0a9c9573c6da 100644 (file)
@@ -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       */
index 5c80cb11518bbe599e28c2c44ac57a03a9f18947..60f3b6b906027e086f3c5a0e6ab4ef0ffa6daaf0 100644 (file)
@@ -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)
index f3799295d231c7d34a114cbb75b8950e6a61da3c..f9a60375f0d0121855af7f3a157afccc909bf547 100644 (file)
@@ -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
index 25a585ce23e68243e1f0a1610f240624aaef6bde..2835b85fd46d85ae47ec857caa93db1ee5ba79b9 100644 (file)
 #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) 
 #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. */
index 5db5942575fe9781f4e06bdb89f6f1e86e1dfb5f..aee73d0611fb9bbb72f3ab52a0b91c09ba861c12 100644 (file)
@@ -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
 
index 1e3159989958efb006f607a5a3755ccf24e2308a..f79c3721da6e772991779c4ee55eddce00f3bab0 100644 (file)
@@ -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 */
index 8c469af939aab33a2117d7361e247371c6303750..bbde90fa58380bb6d6940d9ec7454af7a4d55608 100644 (file)
@@ -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 */
index 558828590a6972f83b923f958a498a90222ad973..935119c698acd27270bbc0b18ae97bf97bf1ae9a 100644 (file)
@@ -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)
 
index a6d7d1c536c33708b84b88661184d4256299450d..5a2991cf0251d558c15d108d9ea88155240425e7 100644 (file)
@@ -157,6 +157,7 @@ enum {
        DEVCONF_DISABLE_IPV6,
        DEVCONF_ACCEPT_DAD,
        DEVCONF_FORCE_TLLAO,
+       DEVCONF_NDISC_NOTIFY,
        DEVCONF_MAX
 };
 
index 0459664c263690a5f4ed7f6e77fd97faf543eafe..2be7bd174751ae393e3c15f702e07308afbcbe16 100644 (file)
@@ -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 (file)
index 0000000..64804a7
--- /dev/null
@@ -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_ */
index 43bfe3e1685b21d7dcf5bbb254a269ec941e5523..86e930cf3dfba3f472046e8cded054a1159a83d8 100644 (file)
@@ -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
 };
index bf1ef65cc58248033c2ea6aedb27385bdd6955e3..649c68062dcaf822741b926ad14664841a3e84d2 100644 (file)
@@ -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 */
index d908d17da56d677e62a07011c852cc38cdf824cf..0e63cee8d810b7ef33832d6f030e4c2dbe246c63 100644 (file)
  *      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
 };
index 7df9b500c80493e944591a2192b07253f1b42669..e3e19f8b16f2de81107fd672476e6496632c8524 100644 (file)
  *     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
  *     %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
  *     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
  *     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.
  *     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
  *     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
  *
  * @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
  *     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,
@@ -2421,6 +2491,32 @@ enum nl80211_channel_type {
        NL80211_CHAN_HT40PLUS
 };
 
+/**
+ * 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
  *
@@ -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 */
index 20ae747ddf3483af636aef6f729fe90a33fa852d..6b7b6f1e2fd6a697dd26427c1130a5b51823d899 100644 (file)
 #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 */
 #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 */
 #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 */
 #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 */
index 94e981f810a21d938e863797f9fad25652ef5068..b65c834f83e903c6dd00c062362a93bfd9a51aea 100644 (file)
@@ -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. */
index fcd768b09f6e898fdccc64dda92d4ac289d58fdd..7a5eb196ade95a229ab8b3950cbdbb15527b60d5 100644 (file)
@@ -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)
index b1d2bf16b33c92fe4f5e27aafe5d34fe87d5fede..b8a24941db21e82b11d80d0912c057a54bcf7742 100644 (file)
@@ -37,6 +37,7 @@ enum {
        UNIX_DIAG_ICONS,
        UNIX_DIAG_RQLEN,
        UNIX_DIAG_MEMINFO,
+       UNIX_DIAG_SHUTDOWN,
 
        UNIX_DIAG_MAX,
 };
index 81a927930bfd35a68f57bff638d662da9d6f6cf8..f35aa0a338c7610d89aa7f9e92e47d7e3a0de0a2 100644 (file)
@@ -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;
index 2470f541af5078c6841a8fd329d0c470b0770b31..848e3584d7c8063759548eb4f440e7b2bf262126 100644 (file)
@@ -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 */
index aafaa5aa54d46bb9a93a8137a22344408298223f..0f7d279ebde35fd1be21cc922def324eaacb240f 100644 (file)
@@ -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 (file)
index 0000000..09c8a00
--- /dev/null
@@ -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 (file)
index 0000000..1774a5c
--- /dev/null
@@ -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/uapi/sound/emu10k1.h b/include/uapi/sound/emu10k1.h
new file mode 100644 (file)
index 0000000..d1bbaf7
--- /dev/null
@@ -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/uapi/sound/sb16_csp.h b/include/uapi/sound/sb16_csp.h
new file mode 100644 (file)
index 0000000..3b96907
--- /dev/null
@@ -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 */
index b576f7f14bc6957fdf04ba0324f7416f78995c6a..7e1c3de1ce45f1520fc9b1ef71507b43c2f08697 100644 (file)
@@ -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;
index aebd4f5aaf41ffaf59e4bf2a12d18600705d08e9..fd996c1ed9f891988607812abb95dc8820ab3751 100644 (file)
@@ -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
index 76b8e77773eecb3120b87faa0a0b23e2b4cb8fd3..1f391819c42fe6d6539f5ba5e66e6f365b877f6d 100644 (file)
@@ -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)
 {
index e2fd74b8e8c250cb9de5ec5650eb32f5d4dcd93d..ff7d9d2ab504ec69da98156f3df39a9b5a868478 100644 (file)
@@ -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 (file)
index a9ae369..0000000
+++ /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);
index 7693aaf324c655d325b1739014c032aba76856b4..afd092de45b71c45a9b3be6b70ed8dc0db085a0a 100644 (file)
@@ -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>
index b69cc380322dbfe17983e582a9537d6e53e1ce7b..61e081b4ba1199c7c7da9f44c6b7f9fa9e87eeb2 100644 (file)
@@ -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>
index bb227e380cb574f9eb629b5ac162fcab8b34b1b3..8e3ad8082ab7074fde4ea9da403961afd2eadc45 100644 (file)
@@ -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>
index 5ffce7b0f33c71d5fae15d8ead377aded9d0fd88..713a2cac48816461c0c0a5b11d5a854ea5c4b3d3 100644 (file)
@@ -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>
index bc64fc1375542415bb258f635226b76e056f1909..9fe45fcefca084b804b37d8a4f782fdafa87f1bb 100644 (file)
@@ -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>
index 7fdd9eaca2c3a40ba08955b0cb9be5dd04e88f04..6698e0c04ead068279a7ed6a106a794b4ee1a8e6 100644 (file)
@@ -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>
index 41faf0b8df1df9f2f5d9cb12eb01980526025ec4..e458782f3c52ac69f88d05d10233fd32b330a7fb 100644 (file)
@@ -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/
index 06fdfa1aeba712283c1e1d706424c1279abaf0ca..06f7e4fe8d2de4046a3139106058b9c831c9b789 100644 (file)
@@ -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.
  */
 
index 1680a0123a139dda2a3e229bceeba303f6b43265..71259e052ce8c516fccf135ffa994354729a142a 100644 (file)
@@ -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
index 22508ef943e6ba841a06f3516a81918b4795301d..88e7293b96bd74df334c6a15b88e55e2de53c446 100644 (file)
@@ -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>
index b7c93ca896d6de8179697b908132b0d34dffb479..518baa896e8375e25fce00ccbbe34709d9984e01 100644 (file)
@@ -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 */
index d187988e2b567b8d36dd2787dae9429bdf792b79..83637dfba110c8308570d7f75ec46bca7386dc3a 100644 (file)
@@ -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,
index dc3036cdcc6a60ac4e8bea6521279b2cff687bcb..c55e26b17d93de77dc069d7f30019f7391e0d93f 100644 (file)
--- 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)
index ee070722a3a36f1916b385e8872ea505105d06bb..a292e8050ef234029611090004f1b46f889610d3 100644 (file)
@@ -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;
index 402442402af710d5acedf500347cca48f89a6be4..4a6d31a082b9e534eadc3fa2873313fa07cc7869 100644 (file)
@@ -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,
index 4819d31533e0e1ffc17e501318b41a66d580d1a6..403e71fa88feb900a7d194f3f3c83f4f6e1cb0d4 100644 (file)
@@ -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)
index 0c0ad930a632f23e4c0661a20684c5d572e3dc15..806fc0a400514b677ca1d74abf1c55a055097822 100644 (file)
@@ -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);
index 226dca9894487fd7fc1b391e827acef905a44d90..8c93267ce96910a48f9eb9e5bb8e295470656edf 100644 (file)
@@ -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:
index 53f5244e28f809a83b3cc3abca10ae5b61f0324e..8d8afb134b3ac016799be9ab43d6fe45f40962bb 100644 (file)
@@ -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
index 8676d2b1d57438d94ba90cef20e63c345880cdd3..e45e3b4e32e3f480b2b65d5900ff0838391bc2ec 100644 (file)
@@ -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
index b02b75dae3a8a5dfeb015838ba5eca2ecb5d6109..9f3925a85aab07e8eae11a1ac7b40e85f64fc480 100644 (file)
@@ -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;
index aea174cdbfbd4689b6ee989dfa9ab710a7f5cc11..5453b17d8df20249c6647bcc5c2485edfec4c1e5 100644 (file)
@@ -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;
 }
index fd8d5afec0ddb372d514367df3a6a81996eeac49..5aebe9327d68c8fd691243f78880c12d69951611 100644 (file)
@@ -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;
 }
index 789cb73bde67acf8f19375d67e8c0ec2322f509f..196d9a0254bcbc6820c5f60f3c53a63638b683c9 100644 (file)
@@ -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;
 }
index 391d4fb2026f9acf7ce1b1f85a0c2f5366152c35..6f58ddd53bff8d2752c7a59dda1c20e40ec428e0 100644 (file)
@@ -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);
@@ -328,6 +357,9 @@ static struct batadv_debuginfo *batadv_mesh_debuginfos[] = {
 #ifdef CONFIG_BATMAN_ADV_BLA
        &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,
@@ -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 (file)
index 0000000..8e1d89d
--- /dev/null
@@ -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 (file)
index 0000000..d060c03
--- /dev/null
@@ -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_ */
index 15d67abc10a43b329ef3cf561bd3fdf456c3c286..dd07c7e3654fa4b3e38f9c0665ca705a332203cc 100644 (file)
@@ -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)
index d112fd6750b0564e1b08232482eb8c1261b749ad..f1d37cd818155ed82b388571a2342afb39509897 100644 (file)
@@ -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;
 
index 977de9c75fc27010c1fd98dd3e11e3aa459ebe41..e05333905afd566117bf1267d6e3ac05596c89c1 100644 (file)
@@ -81,6 +81,28 @@ static inline void batadv_hash_delete(struct batadv_hashtable *hash,
        batadv_hash_destroy(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
index bde3cf74750796142d4a74e1db2be87516152a1c..87ca8095b011517b6f41faf8d1dfa25ef8e0b570 100644 (file)
@@ -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)) {
index b4aa470bc4a6ec675d84fb373a973dd4d224cd5d..f65a222b7b83c0d691f859f2eef1ea189ac84e2c 100644 (file)
@@ -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;
index d57b746219de057c931d8459f1ccef84ce711cee..2f85577086a7cf923c6185f84f6efeb3bfb5fe84 100644 (file)
@@ -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)
  */
 
 #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
index ac9bdf8f80a63360a9b5bec6069a6222e17db881..8c32cf1c2deca7177945a804afcdf6ad10572ee5 100644 (file)
@@ -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,
index 2d23a14c220eb281a839c58650fb9a70802bb415..cb6405bf755cdbdf24b005b38416999e9ec38e19 100644 (file)
 #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;
index 376b4cc6ca821ffb4279e2b4df81e61899be038f..1aa1722d01870d69738f6be60a7e7868882cab88 100644 (file)
@@ -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;
 
index 570a8bce0364ea08ea45341b57b362a72beedc45..4425af9dad40e2b9698f48c576c27042c13a8dbb 100644 (file)
@@ -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) {
index 643329b787ed125102beb687ad1f18c1b4a0ca8e..0078dece1abcd4cf6784b59cf5441ac150424330 100644 (file)
@@ -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,
index ce0684a1fc836f6713ce7cf1e1164e39b4cf0fd2..6b548fde8e0435fece3a67f9ea0f94a1f8aae693 100644 (file)
@@ -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,
index 66518c75c217459d39f7bc8e79aed34b25b20e22..84a55cb19b0b9b2d4e5c9f2d787bf916059556db 100644 (file)
@@ -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,
@@ -493,6 +448,9 @@ static struct batadv_attribute *batadv_mesh_attrs[] = {
        &batadv_attr_bonding,
 #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,
@@ -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 };
 
index baae71585804313ff406aad0ab7f04b0b7daa189..22457a7952baae3fc85c3ce43bd14bbeb5acf068 100644 (file)
@@ -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)
index 811fffd4760c3678a60994e027896277289e751a..46d4451a59ee8feb6ce895473d6df838e97f8326 100644 (file)
@@ -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);
index ac1e07a8045475ed9ce367d39440940f29ab0852..ae9ac9aca8c53d5ffd93b015cb6ff779f55c86fe 100644 (file)
        (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_ */
index f39723281ca1f7cd96dd9f7535a2bea8fbc5aa07..10aff49fcf25adb106cefb020309e456d8f04a2f 100644 (file)
@@ -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;
 }
index 1c46e2eb1ef92615bcdb536cf9d134f3cee0c4b1..61abba58bd8fee1ac6be8b043927d52ddf9f141b 100644 (file)
@@ -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)
 {
index 5abd1454fb07d3025184de6731afad654176ae02..0f65a9de5f749719b9b778cd8c989680b0b1eb4d 100644 (file)
@@ -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));
 
index 3537d385035e61fc090e9094b83850243268f992..d3f3f7b1d32cd06b082142bcbce02c630cd4eb20 100644 (file)
@@ -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"
-
index fa6d94a4602a8352a6f2aa9ed13ed18ff7e6c08a..dea6a287daca88b666eaee999043a3abf6dd853a 100644 (file)
@@ -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
index 0760d1fed6f08bb13404a11622b83cf3dcf02484..2f67d5ecc907e6dfc0ca74fcc21fbf12a527b175 100644 (file)
 #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);
+}
index ba033f09196ee45d7d6fbd170386a0d62af1d4ac..5355df63d39b673d246d131564a1e17dc116c27d 100644 (file)
@@ -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 (file)
index 0000000..1b0d92c
--- /dev/null
@@ -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);
+}
index 4a6620bc1570901c34a1c406ffb83909c27d3348..a5b639702637404d5c1955b36163a3c459fe174c 100644 (file)
@@ -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);
index 98f86f91d47c691b9e6604b73e2e8248f29921cf..e58c8b32589c44811c042a623c48e1ca1d8550a1 100644 (file)
@@ -25,7 +25,6 @@
    SOFTWARE IS DISCLAIMED.
 */
 
-#include <linux/export.h>
 #include <linux/etherdevice.h>
 
 #include <net/bluetooth/bluetooth.h>
index 50f0d135eb8f201daf8156c433f08a973bfa338f..a4a9d4b6816c43b3216eee038f961301978b5713 100644 (file)
@@ -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>
index 6c9c1fd601cac41e879c3e041f103ee645ebd458..e0a6ebf2baa6fecd58a0cc13ea6f2906c6614a46 100644 (file)
@@ -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;
index aacb802d1ee45d419aac1555442bb08edf227dc9..1c57482112b6e5c1eebfa30ce1ac84375db737dd 100644 (file)
@@ -20,7 +20,7 @@
    SOFTWARE IS DISCLAIMED.
 */
 
-#include <linux/module.h>
+#include <linux/export.h>
 
 #include <linux/types.h>
 #include <linux/capability.h>
index b9196a44f7598bf33b0c2bff6d0764eeeba8fc11..25bfce0666ebff70258019ddb1bba9b6f1eca967 100644 (file)
@@ -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;
+}
index a0a2f97b9c6207a600a256415ada30d12fa88f9d..596660d37c5e56d6a0178b16b288a2d3c868f965 100644 (file)
@@ -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) {
index 2022b43c7353ee98d7546d6c9e0ef67c43811d3f..705078a0cc393c023054ad1d55aea1a548e3da1d 100644 (file)
 
 /* 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;
index a20e61c3653dbf84f3c567977757f61239fd2a82..55cceee02a840598d8b8f49d9f6b0ad989719ba8 100644 (file)
@@ -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);
 
index ccd985da65180656d7df83a986655c4b82258220..b2bcbe2dc328ba8473227035c39a7ff467ee5659 100644 (file)
@@ -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;
        }
 
index a91239dcda417f5a862346c981bb941aba44d086..2c78208d793eb8db838cf85a480e029a4dc3567b 100644 (file)
@@ -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;
 
-       return l2cap_connect_rsp(conn, cmd, data);
+       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);
+
+       __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,36 +4384,505 @@ 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 inline int l2cap_move_channel_req(struct l2cap_conn *conn,
-                                        struct l2cap_cmd_hdr *cmd,
-                                        u16 cmd_len, void *data)
+static void __release_logical_link(struct l2cap_chan *chan)
 {
-       struct l2cap_move_chan_req *req = data;
-       u16 icid = 0;
-       u16 result = L2CAP_MR_NOT_ALLOWED;
-
-       if (cmd_len != sizeof(*req))
-               return -EPROTO;
+       chan->hs_hchan = NULL;
+       chan->hs_hcon = NULL;
 
-       icid = le16_to_cpu(req->icid);
-
-       BT_DBG("icid 0x%4.4x, dest_amp_id %d", icid, req->dest_amp_id);
+       /* Placeholder - release the logical link */
+}
 
-       if (!enable_hs)
-               return -EINVAL;
+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;
+       }
 
-       /* Placeholder: Always refuse */
-       l2cap_send_move_chan_rsp(conn, cmd->ident, icid, result);
+       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);
+               }
 
-       return 0;
+               /* Other amp move states imply that the move
+                * has already aborted
+                */
+               l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
+               break;
+       }
 }
 
-static inline int l2cap_move_channel_rsp(struct l2cap_conn *conn,
-                                        struct l2cap_cmd_hdr *cmd,
-                                        u16 cmd_len, void *data)
+static void l2cap_logical_finish_create(struct l2cap_chan *chan,
+                                       struct hci_chan *hchan)
 {
-       struct l2cap_move_chan_rsp *rsp = data;
-       u16 icid, result;
+       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;
+
+       if (cmd_len != sizeof(*req))
+               return -EPROTO;
+
+       icid = le16_to_cpu(req->icid);
+
+       BT_DBG("icid 0x%4.4x, dest_amp_id %d", icid, req->dest_amp_id);
+
+       if (!enable_hs)
+               return -EINVAL;
+
+       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 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;
 
        if (cmd_len != sizeof(*rsp))
                return -EPROTO;
@@ -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");
        }
index 083f2bf065d4d788e59702d29b71b39aaa7bd688..1bcfb8422fdcf55096e9b4131e07eab63d5c365c 100644 (file)
@@ -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);
index e1c97527e16ca352d4e55016b3a1f70b3e40d5b6..b3fbc73516c415ee1654eb6f2aa38d5e390fb00b 100644 (file)
@@ -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)
 {
index 91de4239da6621d6e5b7a2989beb5bd5b883ff8c..f559b966279c13e8d1e0eb36afbcc465067c4e8d 100644 (file)
@@ -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);
index c75107ef89204877315ea8d61248c2fa4e2bddd2..201fdf73720933f9fbbbb3bea3bedd1db6d5bbcf 100644 (file)
@@ -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);
                }
        }
 
index b3226f3658cfda1142c7484b110324115dccc85b..ce3f6658f4b284f627325021d59920262f8a7afc 100644 (file)
@@ -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);
index ccc248791d50239c24fce5c0635245f33f654fa3..bd6fd0f43d2b36f3652127d51f5bdf7e797add58 100644 (file)
@@ -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) {
index dc42b917aaafad3f050177694c438648af2b22bb..531a93d613d4f3f86eff5174cdbb1236b75cfb53 100644 (file)
@@ -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,
index a5923378bdf03ab73a259cd3c74f88b890972030..68a9587c96945cdd3264cc310b68b7be95cfd953 100644 (file)
@@ -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));
 
index d0359ea8ee7901472adee37ff9f22e62d51ce585..e859098f5ee9b11468e4de7159b9d2cdeaa8e84b 100644 (file)
@@ -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/
index 070e8a68cfc63f856b281b4f19e08181cbd5172f..7c78e264019000fe48d4bed8c22a86f6b7b4131d 100644 (file)
@@ -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;
index 76f15fda0212b9756d6110ea0f105edca4b3d25f..4b34207419b1cfbe39ca54321cf9087101bab155 100644 (file)
@@ -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
                 *
index 7222fe1d5460203ad5d1edff1ee5331d49fdb036..cd8c3a44ab7dccbdb82ddb0cba3fe0a8c2e978c0 100644 (file)
@@ -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 (file)
index 0000000..6f0a2ee
--- /dev/null
@@ -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);
+}
index 241743417f498bdc9c8c63fe2500a78f9a4d2126..977c3ee02e65ac26131cad067c3c56fa0aeb8802 100644 (file)
 #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)
index 093f527276a39c097de23cea8ab7e4016df438cc..dead9dfe865b517247723d025cb0006cc5b44621 100644 (file)
 #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)
index 9b278c4ebee10efb45ee07f480f749e609ca891e..f21a739a6186b64f4850c69bea1fc69c7c47d066 100644 (file)
@@ -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
index af9a12099ba4add30e66055fd1a356e16e6813fa..b01849a743101a16e99eebb3a0ef653242c98330 100644 (file)
@@ -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;
        }
 
index fd30a6022dea94311ea7002dc872d978b87d9c3a..7f884e3fb9554328b1e39650d5708a21b9f92a57 100644 (file)
@@ -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) {
index c5c059333eab675aeb73d4bf640f2b784d274902..5913a3a0047b35575fa45ebfd7d3a74cad7b75d9 100644 (file)
@@ -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);
index 13b36bdc76a79f19d48ac3ad35b460dfb77e5e8e..a1ef1b6e14dc0df71bc72bf6a5ca18bdc8d255cc 100644 (file)
@@ -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);
index fd7cbf5aa8956732f51637eeab3f512e00743fcb..3ebc8cbc91fff419097799784dad4aa374ced101 100644 (file)
@@ -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),
index 44f270fc2d0672207e42de6747948e430a576311..a376ec1ac0a7b086354b24f498af65bc4d5fc6b2 100644 (file)
@@ -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);
                }
index 1f5c9785a262e02748b844e325f510f7a8c08dcc..574dda78eb0f0d747eeeb44fb9da74be9618068f 100644 (file)
@@ -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;
 
index 3b6dd3180492109cd8203b6933e7d0af9a3c9c87..ae566902d2bf33be59d944c618b3a9f6a9e133ad 100644 (file)
@@ -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;
index e5942bf45a6d9b7e7412a2100b7ef116610aab65..d0cbc93fcf32d94db2b909274dd60a9fe88cc80e 100644 (file)
 #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;
 
index 4d64cc2e3fa9bf1246ea3504f582616f98060bf1..a8705432e4b1923073b5ed3565daa3baa9d39fa7 100644 (file)
@@ -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;
        }
 
index 3d92ebb7fbcf71471d4b3d90e5309f459c47bea0..c23543cba132bc19a213ed242e47386e8e41ca65 100644 (file)
@@ -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;
+}
index e318c7e98042ffcfd1fc43a1d04b5cf816d651a8..b0901ee5a0025f93e32287c1acbb3ef0ded0f47a 100644 (file)
@@ -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);
 }
index 22571488730a7d1bbc2f5f2ec545abf850dcdf4a..c815f285e5ab76e354dd7752f7ef1c1049154570 100644 (file)
@@ -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 =
index 017a8bacfb2773483c97c8fa3b162e03f09f454a..334efd5d67a9efe9706fcd0feca4f0afc3621f2e 100644 (file)
 #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 */
index 42f1e1c7514f67ad56df06ffe53e6c94a094681a..6456439cbbd9e4160c05105554db665226892620 100644 (file)
@@ -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();
index 77a0388fc3beccbf39187e357c7a1b4c93f09d73..3151acf5ec13afb34480a28a3f4a73deae69990a 100644 (file)
@@ -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++;
index bde53da9cd864d4e5e5baf85e18da5611418a1d1..5e67defe2cb0ef672f7b579d442e34df1f51976b 100644 (file)
@@ -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;
index d1dc14c2aac4ee00fa6dab706131bbe41d3790f7..b29dacf900f9496a42a565a3b2c48ad9cf502c74 100644 (file)
@@ -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;
        }
 
index fad649ae4decbf393c52b614dc8be0aef07e0750..1868625af25e096d1c7886d29ce6c5967ac1040f 100644 (file)
@@ -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);
 }
 
index ab570841a532ea318b5133596f1957192ff01354..57fb1ee6649f65a0994d86c6f8763fe6e14ba081 100644 (file)
@@ -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;
index 3f0636cd76cdcd132278e4f860ee1f581fd8174c..3ab989b0de42a0bfe7905ee99d98901ee9e9a075 100644 (file)
@@ -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))
@@ -634,6 +634,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;
index 8a146cfcc366fbead42d31d882893a74ec8dcf4e..a692ef49c9bb9b2d996f0538049a135a93c26812 100644 (file)
@@ -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);
        }
 
index a7c36845b123c09f727931cfe3ef3e4ad0365432..d1b08045a9dfbf4dbee4255c68cdcd6ad1e026a2 100644 (file)
@@ -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);
index 70989e672304938a39cdf7b7a0dfd87b7497d2a9..1b588e23cf80b561632b9b5e16b851dff218a933 100644 (file)
@@ -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;
index ea850ce35d4acef9ef80cf342a55cbe5e44dae56..662071b249cc627130cf90eeaa8e5b7bcd8b829d 100644 (file)
@@ -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;
index 7b7e561412d379380a54678b1505da796184c49c..e47ba9fc4a0e6ce47295d85108f1d573290a2aa7 100644 (file)
@@ -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;
 
index 102d6106a942fc32a8dedb7832711cbe94b4822b..e36614eccc0476d8c9fd1a3ebfbcb59bf14ffe4f 100644 (file)
@@ -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;
 
index 274791cd7a35df1274e9120d199af84ea9f60dd0..f5eede1d6cb8eb92cbf97b1b37de1362f13ac095 100644 (file)
@@ -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
index 6d42c17af96b4a606a545d2d72ad5e32cb53c3da..f651da60f1618f089c2d21eef069ac5b3648218d 100644 (file)
@@ -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;
        }
index 766c596585631e1001bdd64c80639554c6ab7831..24b384b7903ea7a59a11e7a4cbf06db996498924 100644 (file)
@@ -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)
index 47800459e4cb341c395f54f2d161c300a112c1cf..ce6fbdfd40b893edc29aa090052663024039eadc 100644 (file)
@@ -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));
index 2a6abc163ed2fa9cc15d4be2f4e9e795ec9f08b5..cc06a47f12163ad8b93cae060a8c211bb13fcc73 100644 (file)
@@ -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);
 }
 
index 825c608826de1c4b5dea08c46e6ff4255117c990..5cd75e2dab2c17377d7250680c6b32717fe9cce9 100644 (file)
@@ -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)))
index 71b125cd5db18a3af37d124d4eb3495f3e03fdea..4797a800faf809dd7fae7c958de67181d67e58d2 100644 (file)
@@ -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);
index d34ce2972c8f90bca6809342aab5451c9138241e..2026542d683647b1199c02a8d634d3e0d11f7ff4 100644 (file)
@@ -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;
index e23e16dc501d5458632df5e884149f89b30f9e28..7afa2c3c788f184457e45899a7065a9786d26df7 100644 (file)
@@ -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);
index 7880af97020885a3ae1b1fdbfbddbeaf9c4d2bbc..fa3ae814871082e22121855a4033ddc4ec21b1c7 100644 (file)
@@ -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;
        }
 
index 8d5cc75dac88286fa6a10f24d7cb8f16c7c1bc14..eb9d63a570cd1ce595076096d9b2aea3723a4c38 100644 (file)
@@ -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);
index 7240f8e2dd4511dde4de0bd08290bb718eab140f..a85ae2f7a21cb15502bd69e9c63a1ec29020fa40 100644 (file)
@@ -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) {
index 1dc01f9793d59120a713213e7e65cc855bfb37b9..f6289bf6f3325edc2c78541eca88e546e5ec97c9 100644 (file)
@@ -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;
                        }
index 6537a408a4fb451d906b574def4746c064399fd9..3e98ed2bff55d7328aae7209ecbda4f78445c87a 100644 (file)
@@ -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 */
 
index 14bbfcf717acb9d02df641231cdf30a611a43810..3c9d20880283de0f9b5244eae8184e76d9a20dcd 100644 (file)
@@ -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;
                }
index 858fddf6482a645c46bf441c67d9ed323dc7d78f..c3a4233c0ac290394c819882aeff5ba3800378f4 100644 (file)
@@ -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) {
index 798358b107171664823de1b13cc3ffd020dc7f94..d763701cff1b4aca032e60f335a4208e054a4e06 100644 (file)
@@ -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",
index e15b45297c09f0043bda21ad366ce36d5a6e5824..191fc24a745a9668332f74106fd39831d9f01c53 100644 (file)
@@ -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__);
 
index 3eab2b2ffd34e41fd84588a27c23de0d43e16fc4..a9454cbd953ce700139fdb010a333128b565b800 100644 (file)
@@ -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++;
index 97e61eadf5800f8df1054da565beb227e0479568..3ea4127404d662f6756155128054d4a4c9b4ba0a 100644 (file)
@@ -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) {
index 170b1fdd6b72e26060edb584812be07493fb2f04..17c5e06da6628b7ec12495471d3bfcc943acf969 100644 (file)
@@ -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) {
index fe5daea5214d9907bb742d0ee6e18ca900f07d16..75e33a7048f8b759eee7e4f8cf6729a194c1d3cd 100644 (file)
@@ -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
index a82047282dbbe2513615ae0c0e60dc1c54b2aa92..da2c8a368f68d9c6b72c605593aa5b83e0622344 100644 (file)
@@ -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)
index 8918eff1426d2e5da3aeaa41cb4d34824482da5a..0f9d09f54bd9d781bb74d577185c571fe632b270 100644 (file)
@@ -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);
index df251424d816b460ae268f21d337c57e64452fc6..844a9ef60dbd89f459515101ebb0db6e7cfaa8a3 100644 (file)
@@ -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;
 
index ba48e799b031b3a45c902dff2f8690a8ce2627fa..b236ef04914f99585455269fe2c9a18241088461 100644 (file)
@@ -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
index 63d4eccc674ddd1d297368166792e99c636658f6..d84400b65049e61bc64f8f8eef37e2be2aaf2eda 100644 (file)
@@ -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;
        }
 
        /*
index e457c7ab2e28daf5607e93ef0c31e667f1cec216..1ca253635f7acdda23624c28ae1ead4645bd0dd5 100644 (file)
@@ -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,
index 1432cdb0644c2b16f893de842bcd3b9fdd3c5538..291f2ed7cc311649a72700d65098b6d70ba338b5 100644 (file)
@@ -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))
index 181fc8234a529d5b6663f683e0da19e5ab17c1e8..a13692560e637b215f56c906e3302e5a19a0bc44 100644 (file)
@@ -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 {
index 0c4a643556037871c1c6a202aa99ba338a7a92d5..1ed230716d51baa64501e5c6354ec5e50ff20048 100644 (file)
@@ -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 */
index a7302d974f32ca563e4aeb589a193e7617c396a5..f35f2dfb64017cc3fedd3cd29d0682c14dcaf5ba 100644 (file)
@@ -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);
index 948ac275b9b52ed10c1adaa9f931760a0903c788..5d451593ef16f98c65379da619b08e3d47236bff 100644 (file)
@@ -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;
index d47c1b4421a339a3378ef23646c8f99b41d7490b..b78aac30c4986dc78fcd8dae03a527326baa32a3 100644 (file)
@@ -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);
 }
 
 /*
index b6d3f79151e28251f3b3b5a062869fa9acb64526..2068ac4fbdad43346a1e7d460e8fc20549de0f44 100644 (file)
@@ -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
index 0424e4e27414d3bd6c79f5094d0d3907e62b02f5..6fca01f136ad7ca3528dc19729bd8a7b07c24874 100644 (file)
@@ -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)
@@ -4559,6 +4713,13 @@ static struct addrconf_sysctl_table
                        .mode           = 0644,
                        .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();
 
index a974247a9ae40bdb6c83cf5a60a6432761bd84e7..b043c60429bd45529111d56893dac55aae91427a 100644 (file)
@@ -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)
index 7e6139508ee7616f10996f33d75ae88e56bc5ca8..ecc35b93314bb1b73c70df219c9cf8f125c77908 100644 (file)
@@ -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);
index cdf02be5f191405de1587f4d03b3c12f3fe4cc9d..757a810d8f15a5270bbcdf1f734768371d892e73 100644 (file)
@@ -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;
index be2b67d631e5195fcc7df5b48a4b3d172d5eccdc..8edf2601065af07790500809b8dee9fad0fc8eaa 100644 (file)
@@ -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) {
index fa3d9c3280927934bd7b082077674c3c31d4ad4c..473f628f9f203d2e0c58466f32603ce50a330402 100644 (file)
 #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;
 };
 
index f73d59a141316a12286849e89b6f0213e43f42d5..c5e83fae4df423ccbe02bed8bf31ffd415014ad2 100644 (file)
@@ -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 (file)
index 0000000..cf77f3a
--- /dev/null
@@ -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;
+}
index d9fb9110f607e8c587667147739979f34d52bc0a..2e1a432867c0897f4e0d4439f9c6fd5d3f4c66cb 100644 (file)
@@ -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;
 
index 24d69dbca4d68e2f1d1444796cb3d5c33b0a1fe2..b4a9fd51dae74bd8143b2d32e791e089f1d8562f 100644 (file)
@@ -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);
index 73f1a00a96afcd194e5567c36e2d1956a62018ca..dea17fd28e5037295d56cf517671b479a1bca825 100644 (file)
@@ -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;
        }
 
index 24995a93ef8c94b22224dd344a9d474a72d28cc1..710cafd2e1a9f7a7308ffc4fa82a02abec431523 100644 (file)
@@ -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) {
index 90bbefb579435d3f3c4117f738d38366d0421b33..29124b7a04c8dfb335df69014b5348e22b3fb6ab 100644 (file)
@@ -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);
index d5cb3c4e66f888bf056b4103cfd684f8a3e0a7a0..867466c96aac053c6bf39c956160171a099ff304 100644 (file)
@@ -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 (file)
index 0000000..f26f0da
--- /dev/null
@@ -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 (file)
index 0000000..2e155c6
--- /dev/null
@@ -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
index aece3e792f84ad4cfcc88ada01817c70242b396d..5552d13ae92f8554c04ec912b82317dfeef065a5 100644 (file)
@@ -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:
index cb7e2ded6f08cce17f8fb11a7e7e119e8564d661..a14f28b280f57a040e3d499955419f6c949c5c93 100644 (file)
@@ -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__);
 
index f7c7c6319720246f67f3cdbf09daea76634df0ba..26dcdec9e3a5f6cbbe799402c39bb5d09c9d561d 100644 (file)
@@ -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++;
index e02faed6d17efa1684c2c9b0990506008bdb8aff..ee94d31c9d4d494cdfe2dce1ac812e4e094fe65f 100644 (file)
@@ -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;
index 92f8e48e4ba4e63606412e317c28d2153eddccb0..28dfa5f3801febb37cfd4ab17e010be4cc936e24 100644 (file)
@@ -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) {
index 2edce30ef7338cdf1916eef98b353c7dbbc7bcda..4c02e6ab96e7d2990adcda4afa1dc8bac63e1b5c 100644 (file)
@@ -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);
index d7cb04506c3dac8266780c30a74e1a3fa1320ade..125a90d6a795967f13fcdfd19b3c24e24ce02504 100644 (file)
@@ -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);
index 5d1d8b04d6943df82a68da781a475b8eb506cde3..5060d54199abbc180d7dc87ba072bace2bc167f7 100644 (file)
@@ -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;
 }
 
index d57dab17a18251fcb8c63fc27c2dddfe8bc2a89e..6c8ae24b85eb15f525e2e43a1b0e7f93068e8d85 100644 (file)
@@ -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)
index 8860d23e61cfff646e3e034da7fe4c985fbb5575..00ee17c3e8939b1076ae2c2026ed6dfa1b3f68de 100644 (file)
@@ -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);
index 2d54b2061d68ef3e947168b82a5b041f84ffea50..24df3dde0076bc58d6081f306832c73d568d72a9 100644 (file)
@@ -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,
index cdd6d045e42e7ff2098adebe149640811ad109e0..aacd121fe8c54365607f49e40679d7fd08dcd8e8 100644 (file)
@@ -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;
index 5d6da784305bb26bee73f21f4cc6f2b2f8d4ea17..61aaf70f376e9eafee55cae3cb3b909916d0554e 100644 (file)
@@ -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 (file)
index 0000000..c2e73e6
--- /dev/null
@@ -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);
index 053082dfc93e1f9d0c98e26e9c083fc384ed06d5..22d1bd4670dab741b2417051b45370b4a75b42a3 100644 (file)
@@ -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);
index d8e95c77db99e5bac5b7cab803c82a731e14a697..6cd29b1e8b926e26a7bc0df5b5c5263fc2e23d84 100644 (file)
@@ -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,
index da8a4e301b1b04ec5d8d0d7aa042a328c986e1d9..e5253ec9e0fcd8b80e506956e68b29407b0be3c6 100644 (file)
@@ -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);
index b1e6cf0b95fd9bf3546420e8cb48578d1a7d2190..e229a3bc345dc4138a188282c4ab4f1717882832 100644 (file)
@@ -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;
index 3ed54ffd8d50dfa1ccf5b4b539c5461fae29c4fb..cfba99b2c2a4958144ff4c2a2faa1d98192d7310 100644 (file)
 #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);
index 182ab9a85d6cb5c0ad88e89bab6f5c0d22c380e8..40161977f7cf0b69ecc488d87427e03c88d61598 100644 (file)
@@ -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;
index 26175bffbaa060ad8da6357330ff596a5391cef6..6565cf55eb1e80f9109502995319655147bd1fd7 100644 (file)
@@ -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 (file)
index 0000000..2ec6bf6
--- /dev/null
@@ -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);
+}
index fc9997260a6bc5b841aafc4f3b57cf11ff7ec404..dfaa29b8b2939c03fef13fa416f6fdaef031bf5d 100644 (file)
@@ -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 (file)
index 0000000..0c8934a
--- /dev/null
@@ -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);
+}
index f8c4c08ffb609d2840adb721e395fcbe99a636d7..c9844135c9caea041bd9a680e39da7bba4cf0997 100644 (file)
@@ -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);
index 3f2f7c4ab7210d5948c22a6e417bc0046b1631b0..d8c70b8efc24231358ab50a32f354b69064f7860 100644 (file)
@@ -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;
index 08897a3c7ec764550d518777811fa8e3179a9492..5b426a6465447f954a4b4728f72a6c00966c91ee 100644 (file)
@@ -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;
index 6c4cc12c7414f90341513a29da3097f4c9f9ecb4..bbba3a19e94457378fad759edbe04392f93c1256 100644 (file)
@@ -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,
index c2190005a11410e2f95141fb841dadc051157a8b..88709882c4641f7d147fbeaa9f48323cfc8637eb 100644 (file)
@@ -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))
index 63af25458fdad7afd6ec253ac365a35d26772dbd..b4ecf267a34b384deb9491b51e3b4e81d545dd70 100644 (file)
@@ -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---
index a7dd110faafaf80509d75849ce982744af41d2b2..4911202334d94d0be28c4c2b1541820f65d2dfb7 100644 (file)
@@ -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 \
index a04752e910239821b1bc3110d078c8d81349d4e2..537488cbf941a3699ccaf533d8a9bb92c9788434 100644 (file)
@@ -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);
index 186d9919b043cc41fbaea7aee56e0cb5e688bf94..808338a1bce54666284c9b8f0c6c6c372d71326c 100644 (file)
@@ -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);
 
index 3195a6307f50eeb5e6715a6db0fbecc4fee2f4d5..eb9df22418f08106241c51e6646b3c3d25c2f128 100644 (file)
@@ -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;
        }
 
index 7371f676cf412e54481751d36bf757f42dfa5134..5c61677487cf831324994e24e22528d15f35aa3a 100644 (file)
@@ -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,
index 0bfc914ddd1504d16a2ebf8ad74655d6deb60e53..53f03120db55dc3d2c1e8c775a054182d21dac69 100644 (file)
  */
 
 #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);
index 9be4e6d71d00d736db7eeee2f24a645b1c41b2bb..214ed4ecd739f10ae201e6dfa9112c0dd943f5b8 100644 (file)
@@ -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)
 {
index 090d08ff22c4b753972959c520e87254feb4281d..c3a3082b72e5cde611b5fb89a63829c7fb4eee27 100644 (file)
@@ -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);
 };
index 6d5aec9418ee203b43708499878864548822a2f2..cbde5cc49a4041fa338f74017c2ad72384fb0ff2 100644 (file)
@@ -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);
index 5ccec2c1e9f669165763372176e62fbc2562d049..6fb1168b9f16dabb5f35f8315f28ee8d10d4820c 100644 (file)
@@ -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;
 }
index da9003b20004227b76f5ad89f04ad4445bf7d0ec..698dc7e6f309847373541748c3cc4a2f40b67f58 100644 (file)
@@ -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 */
index 4b4538d6392589897154035f6ab6305e2d3ebb28..a71d891794a40ab96134ec16eef5568e8b5b3eca 100644 (file)
@@ -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,
index c21e33d1abd0d945ba041182dff52ad3f9ed4dc6..8881fc77fb1324c50d79ca6dcc2dd5423d7a18c9 100644 (file)
@@ -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();
index 156e5835e37f4b140fb9261c2c1ed44f73cf8408..42d0d026773090633aec6cecf21d5c6065a4b69d 100644 (file)
@@ -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
index 7de7717ad67d97c7f75afca4c6a8c13fbec63404..09a80b55cf5a1ffaf06fdbe892ac469f6790b2bf 100644 (file)
  * 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);
 
index d27e61aaa71bd7200c527606820f5d5d82c39ff0..619c5d69799980108c03fc3c0c7d6b2553aebb6e 100644 (file)
@@ -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);
index 7d4e31f037d7c4237e18783ec5ebf18cbc8dba52..382dc44ed330a9921764431bc88345728b0eab49 100644 (file)
@@ -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;
index f57f597972f8833ccc5a74a433bfd2ddafe407dd..1b087fff93e70f278c638c017789f0ba7fb4f1b7 100644 (file)
@@ -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. */
index ff0296c7bab8b131f07a9846b608e7b91944a93e..1bf03f9ff3ba74394fb26201dfba3b3fd2e86a01 100644 (file)
@@ -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)
index 25d0f17dec71e74c8c9e514f17155628ce6dfff6..7c9215fb2ac84ec5c17d3ee3d372a7a6bb4feedc 100644 (file)
 
 /* 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)
index 3ab34d81689753e0beaf7af4a9c7c806f9da6915..4b274e9c91a5f19c526c9c91d290c9fc574d4098 100644 (file)
 #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,
index a16b7b4b1e026a9af85b47f0c596e472b2b71ded..aa8d1e437385599de915988444f89448b5bba02f 100644 (file)
@@ -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) {
index 1b7eed252fe9fe0082596d8716c1e0f5e029db7f..7753a9ca98a6c67870f68bd40b22f3af453a3945 100644 (file)
@@ -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;
 }
 
index 2c84185dfdb0c2e9901d86b0903463061ddaaecf..a5379aea7d09d2410c70a3b467a1f336aa32dc43 100644 (file)
@@ -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 */
index 5c572e7a1a71dc76949b993f9f57e79223533f49..79a48f37d4092b27a88b8fa136f15a51812365f2 100644 (file)
@@ -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)
index 3313c117b322a928d17586c766c66bb698ca17bf..dd88381c53b7780dcae3a3b7e47ca0ca56a54474 100644 (file)
@@ -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)) {
index 10de668eb9f64b8e6f3f9509f7db9ad666f36af1..301386dabf88da51f205d0961021e47cdbbb1ddf 100644 (file)
@@ -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);
index 79633ae06fd6720c1a8d7a2f21f69c7594a41c16..8c5acdc06226a47d84e6ba593509a5e0111f126a 100644 (file)
@@ -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)
index fb1d4aa65e8c9e68b347e292a583081ac07c50c5..9f9c453bc45d770ec18cc2746719df7ffa1f6859 100644 (file)
@@ -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];
 
index 00ade7feb2e3a3b84af12be5bfad378bd8907182..580704eba8b8495e0bdbf2268dfdc197b9983797 100644 (file)
@@ -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];
                }
index 43e60b5a7546eba4fd6e5e18eb313b7526d4f5b1..8ed83dcc149fc7f38ca9beaf83a2c67a82c336ec 100644 (file)
@@ -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);
index d2eb64e1235383e9b0e6aade66710f74ec1b4f3f..f3e502502fee27374dc4c183733cbcc95217aed5 100644 (file)
@@ -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)
index c88f161f81185a678335fe3df6201fb8e64c8d80..1489bca9ea97c19ee525ea44c0d1af794ec94cca 100644 (file)
@@ -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);
 
index 101eb88a2b78563965d4477a815bf8069d586db8..07d99578a2b1406aecd72e38934a05ea82d09d9e 100644 (file)
@@ -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);
index 18d9c8a52e9e72d98686778bb7bcab974119e638..a8270b441a6f93249e095c74be849bdf9ce39f9b 100644 (file)
 #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.
  */
index b858ebe41fdac2f20326cfd58fb37840270fcaa1..e9eadc40c09cc20bce9ad37531ef45ae767f62e8 100644 (file)
@@ -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();
 }
index 0151ae33c4cd448e4812b0e9255d47898bf595da..f11e8c540db41b71a310c1717c54a4e2278d9c4b 100644 (file)
@@ -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,14 +1210,22 @@ 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;
 }
 
@@ -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 (file)
index 0000000..f311388
--- /dev/null
@@ -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));
+}
index cea06e9f26f480b48a58747fc98f5665a3ead21c..906f00cd6d2f65053281c617254f9f50681ec403 100644 (file)
@@ -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;
 }
index 8bd2f5c6a56edfa26193de6da2560c88d5ac75ce..c175ee866ff4ab8eb70b72a6b281ddcffc591ff1 100644 (file)
@@ -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
index 1a4df39c722e3d0b871105ea0ff30099a1ed37a1..4e09d070995a129a065b33eb15c0c729913b4365 100644 (file)
@@ -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;
index f30f6d4beea178ed46750131e5840decd8c5238a..1191039c2b1bc38bda25402dd395d7e3b1bbe7b4 100644 (file)
@@ -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++;
index 68912dadf13d15c0354bec108039176b9659c75a..a9c488b6c50d446e1c9e5276553728af83281fad 100644 (file)
@@ -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");
 }
index 778465f217fa975c39af6fb3d7429214dbfe2a51..6d6d8f2b033e0505f88648b9646d3963d3aa10e0 100644 (file)
@@ -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");
 }
 
index 8b2cffdfdd9985e7397a0b800d5e2c28af20a4b7..0c3b1670b0d164cddf2e80717a89737821fd2b3b 100644 (file)
@@ -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"
index 1548df9a7524af0f61b0ed65bd6e1cc3d4731d09..30e764ad021f75bea322afa2799f434bb97833fa 100644 (file)
@@ -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);
index 58918e20f9d5b038c2181b893b0e0458dbd3a8f2..47edf5a40a5939d2401dc11baa89142b9bcd64b6 100644 (file)
@@ -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");
@@ -1723,6 +1733,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,
index c4ee43710aab63ce34657a06ba9d26d3862a6a61..ec664cbb119f658991fd1e18134305ec08b4d5d8 100644 (file)
@@ -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 */
index 8b7dca9ea4222d34476015ed8bbbb9d7ca98166b..7f3b0cc00b7add352264752cd9db38aa9adda21a 100644 (file)
@@ -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__);
 
index df646ccf08a744af9fb1a7f5d16385bd541b22ae..fdd89b9564ea6e537d70cb79fdcb4f58dbd1ce34 100644 (file)
@@ -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;
index 570e31ea427a1b5017fb2e926d9d47d0ac8ad014..c03b6a3ade2f90a4c9d96f8a3a11dceb1b3df130 100644 (file)
@@ -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;
index 022e77e1e766450136340710a0e6c4b063e9a212..c8beafd401aa283f0befa0494e02649359bab83f 100644 (file)
@@ -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) ||
index 1aa5cac748c4ad5ee32cc6c2acb44ce2e9f5e78a..12475ef88dafe571bbc2e031af50890c08d91a54 100644 (file)
@@ -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;
index 50d82186da87a22da2c46302c3b8cf298350cae2..939f7fbe9b46d832ffab36569e7e4b67f3a0bc68 100644 (file)
@@ -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]));
        }
index 5b8eb8b12c3e6a1155df420f8b101b32c29f6def..5de3dd312c0f77ad787ea037378cf1a9eeb5536a 100644 (file)
@@ -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.
index 9f3fb751c49154bac37fa4baa84853a2c0dd0c06..746048b13ef3aff9659b7161199d2298960662ec 100644 (file)
 
 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)))
index cd609cc62721095baf50475d14e80384089f280a..9af653a75825d0568450445ee3f5828622ac997c 100644 (file)
 
 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 */
index 2fedb2dcb3d1f5e831546b59480eceee14e59a84..503a842c90d271bac3a1c8386db92611f2888502 100644 (file)
 
 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 */
index 08dbdd5bc18fc5dc9f23562ac86a66e20dafb897..d6bf20d6cdbef724e310ed26aca7b0098bcf9182 100644 (file)
@@ -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);
index 05126521743e54b35cf0bb8dce99bd41f1696962..e331269946287a42faad5c78fb0b985dd3e0dcbf 100644 (file)
@@ -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");
 
index cc4c8095681ad70dd0c40fa1a5459debed396a01..ee6b7a9f1ec24e4f0a0049ff3af4c6fc73a29752 100644 (file)
@@ -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;
        }
index d61e0782a797db1d4f4548ef583108f08272b6f4..7df424e2d10cf6146e7c3b38eaf0bf86a2bb0544 100644 (file)
@@ -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) {
index 0f241be28f9eec697ea9216c096657ace6eaefd6..08cdc71d8e8714b75782379929fa6b050dafa7f4 100644 (file)
@@ -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;
 
index de9781b6464f0940d391555489782bf63f1c956e..faa978f1714b831ff81d81e9ec4732eb3f167fb7 100644 (file)
@@ -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) {
index c4bc637feb76b3e542ac0eaac9c76198e38188cf..884f2b39319a258ffbaa4360736fd7f83b867195 100644 (file)
@@ -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);
 
index 7bbfb3deea305e4d8434c3af9a68ee6e4531c80f..4e078cd84d83c2c15c70ab4270b87a05e590f4ad 100644 (file)
@@ -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] = {
index 6535326cf07c773ba9166c6cbba16b9e7f29fb75..a8ae287bc7afe00ec89ed8032f3cbd7ea1c54b7a 100644 (file)
@@ -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 = {
index 61f9285111d19ae5b34c59b5d8f98366d0645086..83876e9877f1457e675dadb65a3d299e71e84165 100644 (file)
@@ -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 */
 
index 9b3943252a5e9c0b0dd6d2127606d11ac4e502b9..363285d544a1c7402152e6a7da3a7129d94b83ae 100644 (file)
@@ -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;
index dbb364f62d6f03b593b7b804251f48c2dcf7b845..7ea8026f07c9c843698bb54c68eb236840956bf9 100644 (file)
@@ -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) {
index 703fb26aa48d288fa3de60a79f58b43b56c43f78..9e312695c81813b0f9e854df721cbf49bc029f79 100644 (file)
@@ -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;
index 8d2cf9ec37a850951648640728ab1ad6d8f53e6d..d812c1235b30372b35f7b2866b113a9878b27147 100644 (file)
 #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;
-}
-
index ffb92c03a358a8ce64c9e824a09db72a823b76d8..58a09b7c3f6d50b4cf95a4c139d637a225421aae 100644 (file)
@@ -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 */
index e12d44e75b21f79f266b3dc580fd283aa81b58f9..3158d87b56a816112ad71bb675d61a5e8c07305b 100644 (file)
@@ -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);
index 1686ca1b53a157d8568ae8ac104aeb0f9415d696..73b73f687c580ccfe66648234caab5f0bdc543b9 100644 (file)
@@ -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);
index bb10b0717f1bd1472411ce9b0892750722400bab..8d47c3780fda8f98c1a16f6b6b396ec94c2bea34 100644 (file)
@@ -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;
index 4da797fa5ec57641a0fa70b5dd1e6e517884fad4..c8a1eb6eca2dea3597ba9c96a01b84656bad5700 100644 (file)
@@ -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
index 8d8d9bc4b6ff4da74734d68894a40bfc8118cb6c..60c3bbb63e8efaf1ea9de16e32641de804235829 100644 (file)
@@ -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
index 479bee36dc3e4bab3338213d7d8e3a078bf96d8d..aa64ea441676a1ce9fc8c2417cc4487eaecf2cec 100644 (file)
@@ -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);
 
index 71c6a7086b8f04b4e6264969d21f1ba5a362fcb8..7d99410e6c1a542d91795a40f5e9d8bf9e719c5f 100644 (file)
@@ -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;
index 5fbb6e40793eb61f6e9ff8459812f7df2d81bf54..7bea574d59344f754ad74a1a390a8d742843549b 100644 (file)
 /* 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);
 }
index ae1205ded87fda2769025d09b31c6c21632298a3..fe5e966e5b88efb9d24c24015ad38a3c4642e12a 100644 (file)
@@ -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;
 }
index 01cbc72943cd55887a2aaac52ec045a2788cf9a3..27b313befc35eff1f5cfceb41f8ecf9be618c159 100644 (file)
@@ -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;
index fbf5e815090857af357e28d5e1b6da26ac58b06d..a1a41cd68255a571acf59e4c14b8731c9dd10cb6 100644 (file)
@@ -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
index c45ccd6c094c5b16f258be4ffd7a1cff4433f6dc..df24be48d4dad2ee998bb483bdd4b1d109b24333 100644 (file)
@@ -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;
index 9e8f4b2801f6099ebd5afcff20d2b5ef19e16589..ec43914c92a9fbb416c5170e1d74440bb4dd1bf1 100644 (file)
@@ -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;
index fdb2d24e60bda5fe85d8225c38b25a1caed7c0de..0d62366f8cc3f0e8fe33761d0ec6cc3e45bda677 100644 (file)
@@ -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 */
index 63e4cdc92376eb20e0569c34a5c167d1332c4e78..0fa1e92ceac8869f026a8bf2a61724ce102919fe 100644 (file)
@@ -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);
index decdc49b26d873ebcb62e6bf8047af6f648c483a..6d69b5f0f19b0ab97c779375cf6fa7bf474fc1b5 100644 (file)
@@ -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
index acf9abb7d99badc592592f83b42f4acbb14ef4de..5f98dc1bf03943abfd3315109acf94431858a9e2 100644 (file)
@@ -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;
        }
index c1b5285cbde79fa6c861106649d57728373c4ba4..3568ae16786d513830040ddb020c33237649198b 100644 (file)
@@ -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,
+       },
 };
 
 
index c5e42b79a418073d9ec8de66627c91d4ff3e3c23..87d914d2876aeb029483ab88242d9e4fda6ca006 100644 (file)
@@ -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;
index 8b8a6a2b2badaf61e9c71a174809ca989438668f..313bf1bc848a8c45b755e838fc9cd595e1a833c2 100644 (file)
@@ -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,
index 08114478cb853256c3e6f0aeb63d791887513cd8..ac2defeeba83ddbbb1ffcacb54deec0714fb85e0 100644 (file)
@@ -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;
index 4c4b62ccc7d745bf9ba3298f17c2417b28c563b1..f996db343247aab3b155a27df330252de35761db 100644 (file)
@@ -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);
index 733cbf49ed1f506ae263d50675775e2e96e3356d..c3294cebc4f2d8bb56182004145eac444fbc2908 100644 (file)
@@ -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));
index 14a324eb017b44cca9263701d094f3221a37c9a3..a7bb60ff3b5b6f057c8bf5c7300357a9a926e148 100644 (file)
@@ -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)
index a9033481fa5e867b2264fa9f834a4041786ed166..a9327e2e48ce8450212feef7085f91e446766faa 100644 (file)
@@ -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)
index f7072a25c60465a4b71455bd71282f57cf139a0c..6478079b3417fd460c9011048be234d62b3478c2 100644 (file)
 #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;
 };
 
index 03779e8a262289f9a8178e62e0adf5afc16a9ae5..70af0bedbac4db09c08c896ba0173466e29e9b79 100644 (file)
@@ -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++;
index 94060edbbd706ed11c7609913f1e434e5cec76c1..e639645e8fec8ca365c8fc1bc4fb3650db04b5f4 100644 (file)
@@ -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;
        }
index 44945f6b7252c5c42e3fddf265a610824b6a646c..e84cab8cb7a99a6a07fe26daa9f33c03f8bb3bda 100644 (file)
@@ -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;
 };
index 83a8389619aa7ccc0a490a8f8b664200bee53df9..0193630d306125a62f273db3165e98a306249fc0 100644 (file)
@@ -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;
 
index 8d2b3d5a7c21e5ffb2063621a569e1f6280f52ad..7280ab8810c203ed574131c4c9b8a5ea10cf292b 100644 (file)
@@ -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;
 };
index 8d194912c695ba86afc235c5792556c912da71f3..8c5bc857f04d92dd85986f4c292437223a4de557 100644 (file)
@@ -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);
 }
index a5c95274127990b34de5af72f82e9135cf73aa85..9b9be5279f5dac83f53b1027f10144fe91d6bf98 100644 (file)
@@ -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,
index 865adb61685ac6478f99cc0627c3013574013887..78fc0937948df7b8bc2b865cd28d98a17506cc10 100644 (file)
@@ -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,
index 11da3018a85321739625f678cbf8009380b683ff..4b5ab21ecb24a0732d971f3ce08256a96d496125 100644 (file)
@@ -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,
index 62fb51face8a12a002783ee0dd1f3fea88b4ce9f..235e01acac518ad84d7917b53bb2bd524df8ce05 100644 (file)
@@ -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.
index 102761d294cbe7b470de479be5f07b7c5d4d69ed..65d240cbf74b7513e7dc42effdc7f126bb4fff65 100644 (file)
@@ -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;
index 7ae02892437c25bf1e925d6dc756ed23aabff1a3..ff55ed6c49b24115f4dc78b505da368a34e06b6b 100644 (file)
@@ -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);
index 31f06b633574e8e85acfd288d9d5c574b8941275..6db7855b9029ee26dcd97d73c43862a93c35b6c4 100644 (file)
@@ -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,
index a18d975db59cea34eb0558490deb800f24c10d22..d84f7e734cd74071144020490862d91c65855ee9 100644 (file)
@@ -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;
index 564b9fc8efd3c8778ef8ba155cf17f79d92a9a80..0e19948470b88ce8dff6c3e1cded52a6121fe7ea 100644 (file)
@@ -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),
index aefc1504dc88f8b07963c390417f6dbf26544fa5..5d81a44785141680922c5f80b2d9ddcb45ca2e74 100644 (file)
@@ -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;
 }
index 9d75b7761313c5789ca51fb47d5f0fe49fec6966..d2922c0ef57a65047e82e9fbf8f1a890dcdbea85 100644 (file)
@@ -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;
 }
 
index 0a4b2f9a0094185ff43271d7aa01ad00c3d4d6dd..5da78a19ac9ac5af653f8f07ba6e2c8deb634683 100644 (file)
@@ -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;
index d1831ca966d4540a2ced9eb88539817773e36898..accec33c454c720eb864bf21a7afc33de5100658 100644 (file)
@@ -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);
 
index 9687fa1c2275c76cb7033a83657068406d716de7..6ed37652a4c388df5f96dde4f4e865d86e1868f6 100644 (file)
@@ -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
 #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:
 
 /*
 
+  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
 #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;
 }
index 126b014eb79b495dff682943bb49e151a3faf677..a9edd2e205f4eabaeb842ec06406d0e61ec83127 100644 (file)
@@ -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
index b1ef3bc301a5ad424fb041c0f6f37c010098bcc3..b45ed1f96921285bf75badfeaa5caf922118bb4d 100644 (file)
@@ -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;
index 1859e2bc83d113d1a14d01f904475b01099e0626..17a001bac2cc3c81ab052c2b603b02091bd924e0 100644 (file)
@@ -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;
index 397296fb156fd094169db1cacb0f940d936c6bc6..2d5ad280de388d07f3949a578ce6bbdf9cf6ae5f 100644 (file)
@@ -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);
 }
 
index ea14cb44529528124e2bdd24988a59f1cacc2569..f3f0f4dc31dd3adf33033e071e02cb891b982719 100644 (file)
@@ -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;
index 4e90188bf4895b95f89cdcd9ca0f024c31bbe08a..f5200a2ad852e0ac9e14593a070fac3ad6e66558 100644 (file)
@@ -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) {
index 1b4a7f8ec3fd9186fdb6f6fd7cbfb1e9956c29cb..379c81dee9d1256b3a1af84b84bc23b28092f12b 100644 (file)
@@ -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
index 9966e7b16451230319f63d601284281970226799..8c19e97262caf78fae564c09dd679dfc31e252f6 100644 (file)
@@ -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();
 
index 2d518425d5984bf954c6ebba3d7db0abb7ef5dc7..2c7785bacf744491524ee60dae73e5924099ad99 100644 (file)
@@ -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);
index fbe1636309a75ac054de225fe4d1cf245a3923d2..e1c5fc2be6b8f2f245c091c54a927d1440abc1ee 100644 (file)
@@ -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)
index 6773d7803627ff15f9a5d2c144203d17226d9622..c9577754a70825cd00da2a24854a441c93dac09a 100644 (file)
@@ -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;
                }
 
index b6adef8a1e938d22b5cab026597e6f82c917794d..618ec7e216cae9bb17038c07ff5d87a75c8f6208 100644 (file)
@@ -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;
        }
 
index 406d957d08fbcb7d9cb532a8143d363c277c3ec8..9e65758cb03814f9372eafbf86c4821af124be00 100644 (file)
@@ -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;
index 70e3ba5cb50b319319e60c7bfa6fae69bc5c1fed..043889ac86c0419b3d368481b202864077034efa 100644 (file)
@@ -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",
@@ -146,6 +151,12 @@ static ctl_table sctp_net_table[] = {
                .mode           = 0644,
                .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,
@@ -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;
index 206cf5238fd3ef00183f87e52734398ab475fbdb..4e45bb68aef0c7abca77a476f52ac0a9fcfd1f94 100644 (file)
@@ -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;
index b5fb7c409023ff8adea81d41e68ace60781febae..5f25e0c92c31e48460536cd2bb0fc29549172b93 100644 (file)
@@ -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;
 }
index 360d8697b95c33408d6a4913b9b1d497d27e5ee7..ada17464b65bf23a089c036fba47989a2a1d4b8b 100644 (file)
@@ -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);
index d92c490e66fa84e432f11086642c091f5831da65..2ca51c719ef984cdadef749008456cf7bd5e1ae4 100644 (file)
@@ -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);
 
index e3a6e37cd1c536cc93d5caa850219e4104bb646b..9bc6db04be3ea7cd998f41187ff40b19baa9c920 100644 (file)
@@ -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;
 }
 
index 585460180ffb22df0ac0ae966ecc49cf87dcb8cc..bc41bd31eadc064a112fddb3066a9ee9d3405b9d 100644 (file)
@@ -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
index e4e6d8cd47e6fb8ec63c2cd6893c663b79f3bb0c..54f89f90ac33e2b795c9e48c01e625c8248f4d18 100644 (file)
@@ -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");
index 4ec5c80e8a7ca0b20c7291db9641636f4dc0a3a6..aa62f93a91275b355b994c66318fddb8b42e1af6 100644 (file)
@@ -279,115 +279,30 @@ 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
  */
@@ -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);
        }
index dd4c2abf08e7de95085fb6b3e9e87cf22eb4b9ec..39f1192d04bff34dfd2295cbe99b491d603e7cbb 100644 (file)
@@ -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 */
index bfe8af88469a95b5012d1cb34e3e9415120a2808..fc05cecd7481652dd57431727dc2355d39627859 100644 (file)
 
 #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;
 
index 50eaa403eb6e696b6a8e8a9a552f9ca60eb25e2b..1074b9587e81ed57a77bc20042c829be18bfc4a0 100644 (file)
@@ -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);
                }
        }
index a79c755cb41714bf40c66de615ce6d0cc737cb3b..daa6080a2a0c459a663f6453247a838f43fb0eca 100644 (file)
@@ -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);
 
index 6e921121be0616f9f1e1bca2a7625adb527fade3..c048ed1cbd765aa3417c945d2913d0c994cb7d3f 100644 (file)
@@ -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 */
index 55d3928dfd6702c423c04abea5aa7ec6fc870d2e..e0d08055754ea656ab1afdd5dee59a51f16bb163 100644 (file)
@@ -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);
 }
 
 /**
index d21db204e25a181527822fa02599e391b4c40fe8..48f39dd3eae8801ff2eb1638b7ac4551c4035237 100644 (file)
@@ -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 */
index cfcaf4d6e4801c5047f665a8c4b272948e260bf6..3c189b35b102a378914b59236f555438f7c198d4 100644 (file)
@@ -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;
 };
 
index 07c42fba672be17a4a127b8907f52a3520801f1f..18098cac62f23e942b6c3e42839bb3c2e4fdcea3 100644 (file)
@@ -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;
 }
index 4660e30657906bc318494f91485e2826fac46c34..fb66e2e5f4d1a93348c24e212946d74c776c0331 100644 (file)
@@ -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);
 
 /*
index fd5f042dbff4d8a8a47c2a532e0d0ac5d0a70cd2..9b4e4833a484f959a891d5022ff468c671f38239 100644 (file)
@@ -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);
@@ -1125,6 +1121,39 @@ exit:
        return sz_copied ? sz_copied : res;
 }
 
+/**
+ * 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
@@ -1153,6 +1182,83 @@ static int rx_queue_full(struct tipc_msg *msg, u32 queue_size, u32 base)
        return queue_size >= threshold;
 }
 
+/**
+ * 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
@@ -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);
index 0f7d0d007e22b9cbe94665c19b1d1ac2d6328f02..6b42d47029af4f2d959a593578fc68bd174ebce6 100644 (file)
@@ -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;
index 06748f108a5732e9f847cdffd0dafe0cb996c191..5ac19dc1d5e4ffe31394f7f8721efb7a0c2073bb 100644 (file)
@@ -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:
index b34b5b9792f0eb7dd677525b543082d4f521115f..8800604c93f459e1db124aa2a9cafb1a7b5cdb8f 100644 (file)
@@ -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)
index fe4adb12b3ef494e407b9531a62624869158260a..16d08b39921071479456e2033c5e371d381175b7 100644 (file)
@@ -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
index 0f7e0d621ab0e78f7f15b08a2b218fd61bd773a9..a761670af31dd7076b32e7f61f26bb4b94b22728 100644 (file)
@@ -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
index fcc60d8dbefa2bd9a4ae96b42aa4c8b67271cda2..324e8d851dc4ca67fd0ded84a927e782c3647c8c 100644 (file)
@@ -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;
index 2f876b9ee3443b05efc54445b747e7ee7101e50d..a7990bb165295bcefbd88c6396026e2db8b7fa38 100644 (file)
 #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
index 3f72530520883ae4aa510516bf7a4ce641c646d8..14d990400354200056e99d14132d6e7ab2504ccb 100644 (file)
@@ -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;
                        }
index a343be4a52bd0e16b0fdb41e565f39f3d705c823..3563097169cb3ca8b767e9f5398a741c03a9885b 100644 (file)
@@ -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,
index 7eecdf40cf80b3420b745ff044896948c7492201..48c48ffafa1db51d9b96ea2d5a418e592dbcf436 100644 (file)
@@ -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 = {
index ca5672f6ee2f79925906e78dcb188ebbd32e17a6..9b9551e4a6f9780a6b9fe6096949f9f86fd315ad 100644 (file)
@@ -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) {
index c384e77ff77a4e8c2f62398c7559361c5033ad03..f9d6ce5cfabbaebfc202f2d0290d8b1f0fbbc314 100644 (file)
@@ -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;
index 904a7f36832531cbe2fa3d50f220b94775eaf8a9..5e8123ee63fd316d48e224fe65b8336300ec2b79 100644 (file)
@@ -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);
index 0418a6d5c1a683f95542c64628e66f487ddea196..f45706adaf3411813133704d41a12aa9d1d59712 100644 (file)
@@ -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();
index f6153516068c30dce59e4283d9abfc0591adebfb..2acba8477e9db41a196e7b2a83aaff057d3babb8 100644 (file)
@@ -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 (file)
index 0000000..6c0c819
--- /dev/null
@@ -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 */
index b75756b05af76374cf62b432249be933881bc594..6e5308998e30738377894073acd7b0e824db9687 100644 (file)
@@ -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];
index f023c8a31c60bc82ad54659957169cd0d974d074..4c0a32ffd530daabb18912edb827c968456a26fa 100644 (file)
@@ -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);
 
 /**
index 9730c9862bdcfd624af15641deefe95c0b12c8de..01592d7d4789e389fd565e7cf9fb194dc7ee7bb0 100644 (file)
 #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;
 }
index 6f39cb808302380e05fa70d9a68925f7a35dcae3..f2431e41a373d47b12422642b73e00068834cdd7 100644 (file)
@@ -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;
        }
index ff574597a8544030ef18b2e2186354ef46511bc3..9bf6d5e32166c47f315c0c8819a84128b857bc1c 100644 (file)
@@ -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 (file)
index 0000000..95f997f
--- /dev/null
@@ -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 (file)
index 0000000..2134576
--- /dev/null
@@ -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>
index 2762e8329986afd57efd3f7735d1904e221ab05e..16d76a807c2fac022294aa33cb0336bb89bab38b 100644 (file)
@@ -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)
 {
index 494379eb464f43c6b33ab44290075044ce06a413..d997d0f0c54a683fb0aee287d44fc79d4b15230d 100644 (file)
@@ -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;
index 1f773f668d1a557ae2712195ed510c3b9a2405b3..fb9622f6d99c4b6b6c87f8a8d8e2c88e4fb3705c 100644 (file)
@@ -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;
index e5246fbe36c4e661698242370b800043e12ce545..2906d520eea7c2b7636fc94f3a60f5131701f57d 100644 (file)
@@ -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;
                }
        }
 
index 3efb07d3eb27425c8b9b5114c925eb9e7f402c9e..765f6fe951ebc7ed8fabaed3a4dc6ea4299aebfa 100644 (file)
@@ -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;
 
index 380976f74c4c90f0159c11740be35dc40602c6c6..05a6e3d9c258c0815e870db6660fda8e4802d31f 100644 (file)
@@ -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;
index 421f9844433519eac0c41e24265d2be9c1155b49..eb872b2e366e1209993efe470bed7f614a299098 100644 (file)
@@ -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) ||
index 46e7aff80d1a8d1b2ea054d1febc0e8ce0404c35..28b7615678154180c16d950252dea460c2e8e29e 100755 (executable)
@@ -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 --";
 
@@ -2038,6 +2041,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
@@ -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,
index a58f712605d83105b6d32e1b966436a454331a90..86468f385fc8ef1ac0422afb117114f8d81b6ba4 100644 (file)
@@ -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;
index d309e7f472d86ae7010f99edba87ced2c0957727..370a6468b3ba662ffe08d89a8d3e70bf6a540a98 100644 (file)
@@ -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[] =
index 5119fdabcb98728a0d0520fd9a69c75a8fe11f6a..aa5d8034890b5f6d3fc7ede653862e17bf46b9db 100644 (file)
@@ -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,
index 48d7c0aa5073d43897b126fdbc743f84350f1783..6fc0ae90e5b1de99992b288d35035e2a0d061df2 100644 (file)
@@ -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;
index 4e1fda75c1c9fbc335b6b45fd34871e8ce0a1898..ec54be4efff09c48ec1ff7a5b09318a831ac563e 100644 (file)
@@ -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,
index 277ebce23a452be6cb027590eb997c278971eba8..071ce1b5f2b40bb7b6d1558ee28f42fc1a99dd96 100644 (file)
@@ -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,
index 9052aff37f6460fcdaba020f0b44d85484243c96..79d6bda58753a2c575969a5fea2c56008eb9daf6 100644 (file)
@@ -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,
index 71cc3ddf5c156075be1bfbee065e9899af8f806d..727ac44d39f4a64f7ba203d8dd839caaa66c15ec 100644 (file)
@@ -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) {
index 030102caeee96b8080d9af6f2c99217278ec5a86..61798f85d0301f51087312551a677167792eadf7 100644 (file)
@@ -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;
index 91cdf9435feca986cf3be980412b7d21a9dddecd..af49721ba0e38310183adbe01dcb1f8acaa3d4ab 100644 (file)
@@ -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;
index f42c10a43315afdbe3761e6ef86d4fe220387124..c4840ff75d00a97ebbe12e3820ab43dd743a785e 100644 (file)
@@ -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;
 }
index f9ddecf2f4cd7a17ebc0d5f0ba92405c03ab904a..09b4286c65f9d7d6e7ab8abed498ad2d7f96e737 100644 (file)
@@ -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))) {
index 60e8fc1b344041d27086d4dfde7786b8d8ac85ec..040c60e1da28f346aa049737802a43ce853940d3 100644 (file)
@@ -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 */
index fe5ae09ffccba585392e786f26942265e0d90650..7d02c322ed9398179ea6bde8a0683a457630549e 100644 (file)
@@ -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
index 0fe6d64ff840f02cdb17df4c27721f8e9a953cb5..3d822328d383211acf226daf6dce7c5252991c02 100644 (file)
@@ -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,
index 54bb6644a598a8177e3fbec4220df2966abd6131..fd798f753609c81a64e6391132d73543cfbf1761 100644 (file)
@@ -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,
index 6c83b1aed288a8d8a7bb08bf142adf954218efe6..8125a7e95ee4dd0bf93dbd07291abb17dbcd1347 100644 (file)
@@ -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;
index bc03a2046c9c60e6f7f939df86537408e70bb04d..da1a29bfc85d7a21c91f8efb6f29edaae6fa0677 100644 (file)
@@ -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;
index cad73af3860cd0f56fb82ee9da909a53627dcafc..9f1815b99a15235ec2923e39ed040998ee7a3448 100644 (file)
@@ -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,
index 2d5514b0a2909d3ad47fd9ab1b81d8c47e0b9917..4e0dd22ba08eddbd7aa744c12069d4417d4f7307 100644 (file)
@@ -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,
index ef171295f6d46b3684667dfac434196f5a9ccd3f..7a5fdb9b0afcd000acc649042a38f182cc280f4e 100644 (file)
@@ -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,
 };
 
index b5e2b54c2604ecb398e5fcaae6c5a873a2dc1cad..b874b0ad99cd2ba7cd8fea316c53ad225a2220d1 100644 (file)
@@ -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;
 
index e66738c783338bc4b98d2bf7daded2e4d920dcef..d692749b8c9b00338526a4958839eafd3343fbf0 100644 (file)
@@ -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);
 
index 434981dd4a611966b9c6f9d4e695ca23c58fb7a7..29ebaa4ec0fda8ff02bc36daa41f9e26927c1e66 100644 (file)
@@ -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;
 
index 6f633f4f3b96e83378db293a4dc6d3340261b507..f1e1defc09b1e70beaf32921a3e6124aeab06747 100644 (file)
@@ -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;
index 8364855ed14fbfd7b3d2af81c7edd0914b6792fc..991018df7131d957341ed11e2c5bde91ea34d8cd 100644 (file)
@@ -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,
index 86700671d1ac12e8192f7400fb2d7fc8a25a66ef..7425dd8c1f095072d3163d98ccd5378594627886 100644 (file)
@@ -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,
index d7d514df90586439592a525db37e9930ef8fc7c3..cc4be88d73184a6e538a4eb961c3f47c182abdd0 100644 (file)
@@ -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,
index 4a1fae99ac553e69bae361bce765ee39f82ebf97..3014b86362bdcaff723bc45b3567fb7d5fb02e83 100644 (file)
@@ -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);
index 26071489970bebcd8af0aa5f86bd626d01b8f42f..ea063e1f87221e982558ec892024e5bdb7793b89 100644 (file)
@@ -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
index d71ed8935f76603e9a75217d2f34763a3ca03f82..460179df5bb526ee06f90fa7ffd03ef638024e3b 100644 (file)
@@ -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 (file)
index 0000000..844a555
--- /dev/null
@@ -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);
index 297244e658d9158663239d9744fee44aec00ab6a..d6846557f27089f11741a7f4e50dc22148eb6a88 100644 (file)
@@ -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,
index a38d9643e9d8319dc38c4e3379d83d13a27e250c..affa13480659e4b302606b182ae5e4dc6d72de6f 100644 (file)
@@ -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
index 2c2f829c3fd7b91ca38a2323272bdfab9421d217..26ce26a5884d7254e6b61ca0f6fd1df2acba545c 100644 (file)
@@ -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,
index db64df6023e0fc3cf8dc53ff6f1b6e7349efb7fa..f0fd98e695e323bdcf1525ba0c038b0f2c358496 100644 (file)
@@ -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;
index 2af77faefbb1734fc5822b3753fbf1c8b046eee3..c214ecf45400a1c7de02aacaf0d68b6495ae719e 100644 (file)
@@ -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,
index 4d50c69f3290969f416333754a7798a91d9df1aa..d26545543732dab8b0805a97dbbcb9f40ba22b28 100644 (file)
@@ -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
index f7cdaf51512d05d26ca93baf8ce2627375a8af43..10f08a18fe3ba7b9bd7789a343f40575a4a4cf43 100644 (file)
@@ -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,
index 6a2c78ef1d8fdf46d41bd90aed88d7b688f32a2e..db301ff94ec2ec43611beb6a86c495fc6e475fa6 100644 (file)
@@ -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,
index bde60139bb95e0ff49348bec3f869242e3c591e3..a7369fe19a6f045fdf5098ed93660f07997489c2 100644 (file)
@@ -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,
index 7bd5e337ee93b6b205fc9202c8ee94f03abb2fab..c707c52268ab44aed2d1165079e889c6470de344 100644 (file)
@@ -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,
index 99dda45e82f5a33c0130db4ca36dc1c7bfdecb1a..aa7a5d86e480412b1bb2da2411847e5d574d0880 100644 (file)
@@ -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,
index 740c51a1ed7bfbd5a508147990e67dcd30b46c15..252e9fb37db34bc862627255e129f1f36f50ed86 100644 (file)
@@ -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,
index b036e60f62d14b02ec672aaa43f37e866fc1098b..102874a703d4cc8c53e98db88728215ef60cbec6 100644 (file)
@@ -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,
index c20baafd9b7cfc0acfb02a943078da333ef294da..24380efe31a11099417f3422838f5854249cf286 100644 (file)
@@ -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,
index 55e20782858d75baec9b48cf119e7740ed99134f..672184e3221a6e2765accc287c8e7b47596ff235 100644 (file)
@@ -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
index bf63336716130a438c1c61e4020b8714dfe15c06..16bca4e96c08a01d5af759c95626b7bcbcc53065 100644 (file)
@@ -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,
index bc10cc26e5f94361594f76aaa8856b6347ccb133..0b9c2426b49f05608a3e0c099a9efdad20157cdf 100644 (file)
@@ -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,
index 41c3f448745ff14f197b1c5715fed49b12ebb386..c309a5d0e7e12e0eba6a3fc8a4d1414aebf5408c 100644 (file)
@@ -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
index 3fc8b66fd167fc98bbdd42c29b889920f5c104ce..78bc5744e89a0cb66a34628916632186c8dd3029 100644 (file)
@@ -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 */
 };
 
index a168ba3313ac3449063edb1aacfc6654338a43b8..dbac3a42347b7db65a2394daeebf4a6a86529f41 100644 (file)
@@ -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 */
index 29cc8e162b0276bc380132ca78c2fae07293b798..ddabb406b14cbacfe660678fe72326fab49bc15c 100644 (file)
@@ -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 */
 
index 1de59d4414260a6c6a20b9454c112eb99d0f08e4..031dc69b7470a0b9d6f3bce39284a6c94474a9e9 100644 (file)
@@ -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;
index f6cc0b917ef03bfe5d38f619e1b3341a42cacf39..075777a6cf0b3d165ff27d537eb48a9573d6b1f4 100644 (file)
@@ -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,
index 4a7ff4e8985ba2fe3b71ac7b57a191e694063ae2..c3da1df9371df1c4c5cce4c6c00001906d270395 100644 (file)
@@ -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
 
index 2899c9fd1ceb4c12a34d01d714ec1bd3d4e74767..b41ed8661b237abd41676cf2bed810686028e046 100644 (file)
@@ -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,
index 2aae6a0efbcd3a2a05e40f896fc0374be7e3eb3b..45fcdff611f919263d335875144ee67dc78585bf 100644 (file)
@@ -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)
 {
index 410758c68090397d2747af150f5b2f8cbc07c9e2..4961da4e627c24878c5cf0537cf70ffd90c8b221 100644 (file)
@@ -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,
index 39b8eca152137434e32cba0b0e60bf6ecba444b2..50dbec454f9872df065c54667d77e6ac1753f635 100644 (file)
@@ -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,
index ab5cebea52e17156f542d5e87006dd490adbdd20..237d964ff8a6bcd49a955ff266f19494d6fa3cec 100644 (file)
@@ -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,
index d97d0f381817f633364e5041a6b3fb41e1828c9d..5376ebff845ec4a091dfc38349b7d6c337633bad 100644 (file)
@@ -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,
index 8490f59709bbf5721786bf89da622caac9f8cdc8..42a009720b29c2e89201e923b6160c4f3ed52136 100644 (file)
@@ -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 */
index e0a73271cb91aff3191d4e32753ac17d91715ca1..fe5dd982bd2384a6e14fa837292f4f381b092352 100644 (file)
@@ -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 */
 };
 
index e51e0906050b59ff09f25b450d397031ff34d921..b77883c7ee762f5ff86891754f31a536627e3be7 100644 (file)
@@ -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;
index 65329f3abc302f91b76c2f139e87e1862cfa6cbd..7dc9916822977d1eb739fba86a57caeae7a87b0e 100644 (file)
@@ -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)
 
 {
index b1bf8d4e6494f4561ea2e11a407f4663f5882f98..a2f87f9488ee163e336350c3c1b7cdebb48dca24 100644 (file)
@@ -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)
 
 {
index 3f3ec0bec0671675de52887586f9f672f06d4431..224f54be15a61002ef17630acff78a191a501039 100644 (file)
@@ -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;
index 5f88d1f09ffeef01f3fd9d0cc1a5746972ec1e90..7420c59444ab41c442cb774be05f869019c5fc86 100644 (file)
@@ -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,
index ceaa593ea4ef632d9f8ad4a6333ded19c0602684..01a03efdc8b042059668e24274ac25799af63029 100644 (file)
@@ -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,
index 98d23bdcaf21bd0208e82bc82d53ee569b56600e..4918b7145b736ef16982bd72131f2b773c23dd79 100644 (file)
@@ -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,
index 52d06a334e8f1a20ca43da9cc7dd8a347680b646..2a44cc10645924820972e8a1cf90e00ac5881ab7 100644 (file)
@@ -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);
 }
index b2b3c014221afd4d6b2079c6a3627f64fcfe9480..048439a16000ef08a8ead209285240224ac2683b 100644 (file)
@@ -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;
index f47f9e226b0823c35970fcbed96096e18042d15f..0e66ba48d453fd9e81e431623320d8e86f3ad758 100644 (file)
@@ -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 
index f99fa251228623a161c6bcaed0d2622f5bf132bf..947cfb4eb30cbd6ed7722bcfa7037bd0f2735f05 100644 (file)
@@ -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
index e672ff4df2da15969f29a3882e541bd3ae441b7c..ad8a31173939d80a6738656579a2a88bd793ac86 100644 (file)
@@ -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);
index cadf7b962e3001956db1f9035a1da0e4d7dd228b..3bf0dc53360ab5fd2a550477feb05a4584df1046 100644 (file)
@@ -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;
index c7e3c533316eeb72e0873353478354caa7594aab..136a393b70abc98dcbe5f0fee9d9c0247b51b375 100644 (file)
@@ -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,
        },
index 5af3cb6b0c18d36345aadfefee3d509404bbba80..864c4310366b4da41ad891ce829d0e2fc0a10300 100644 (file)
@@ -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,
        },
index feb2a143683079df95f47384f0b52c9621a0a03b..61efda2a4d949f56d4ace3b82daf1fe37dc4660b 100644 (file)
@@ -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,
        },
index eedc017c1cd8f7f65f537ddca7c445c6e3b14111..3536b076b529ab8c25edf1292a62e713e841b800 100644 (file)
@@ -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, */
index 456a758f04f6112ee7c75bf2a9c842cc711b70c3..ac9163770013a8adeab493ff4585f70899afd6c0 100644 (file)
@@ -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);
index 60915620556289dd4701ea6434b797e485d1f7b4..ef5019fe51930a7cedda5bc32949633d950dd878 100644 (file)
@@ -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));
 }
index 2614aff672e2c8ccea387a96bbe7e97604b2ebb4..0d767e10ac48f07a9cb03e15995f3a7fcf85223f 100644 (file)
@@ -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);
 
index 368df8b0853e218ca48b92553ccd653d8b406195..a67743183aaf2b77a6aeaae5a9b8e5089e0672dc 100644 (file)
@@ -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,
        },
index 6fc03d9f2cff451c2b3db77a525c64cd984c6b92..d0bec7ba3b0d8f3eb610807525e071ed53c4e220 100644 (file)
@@ -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,
        },
index ffc376f9f4e46f03d61aa808c48423d93e70748e..b157e1fadd8fb3b014575cefe8e3f317bc3747f3 100644 (file)
@@ -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);
index 9ae8b3b17651d84bfaed89c015da17e3290640db..aad831acbb170f282e1287863037ff81095b14d2 100644 (file)
@@ -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;
index 525f881f04096bd25cec390d0a2a26443a93aa0c..ae59dbaa53d919dcdc12de63f24cd1cddbebe3d9 100644 (file)
@@ -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.... ");
index 278ed8189fca9123d7360180fdb9e4b475f4b197..e7220533ecfc79a46f9ab05f3d54d083216dc16d 100644 (file)
@@ -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;
index 30a456700d899bb88cbc643d3d5ea782a2f3d684..280f86de223086ab1b26d2639e12334ab2dceb37 100644 (file)
@@ -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;
 
index fa13efbebdaffc8c7fb5b938838dcac8ea6ce660..a58298cfe7e04f03ce681b4d73540ef688929b9d 100644 (file)
@@ -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;
index e6c6a0febb752ab75c951a16dd08e1be01a2dd2a..29e5945eef60dea7af07e4cea22202d68526b616 100644 (file)
@@ -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;
index b2405020284c6476814b8039a27cb416d64bf668..a4184bb277617fbc3e87bae54b8e1b26c5c722e9 100644 (file)
@@ -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;
index 0f804741825f7ef9db7f18f5bb0bd358188bf3c6..08e9a4702cbc4cafcd34a9d52c2219da0c6ca441 100644 (file)
@@ -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;
index c03b66b784a377ef22135d81de415995c9c163d7..1204a0fa336889c0bc92600496520e2b07961b20 100644 (file)
@@ -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,
        },
index b6a95eeca095fe922d8418c4fd05ee5bcc7fe337..cdd100dae85559d0619e474ded3f198519327bd4 100644 (file)
@@ -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);
index 65c55910566b24eb5dda03445a0e50f0f848bfe5..1610a5705970790973d0eecdd6b34d36c1d4506b 100644 (file)
@@ -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,
        },
index 68eacf7002d6ee87b848818b06a6997236d00426..27de0de900183e17cc0ef8d0c55bfa2f81cc8c0b 100644 (file)
@@ -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;
index c694464b11689136eff0b2afe028d10be789ebf5..4f9c2821bb31188ec2ff9ca9d55999b64bc1a5c7 100644 (file)
@@ -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;
        
index c7885117da334c3da81b41a582f1126f4e4f7489..8bbdf265d11d240ab6798b8b6d67a65a693a8d2d 100644 (file)
@@ -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;
index 22122ff26e34aacabf963c731f645aabb5678158..c617435db6e6532a1caad658a4cb7773bc252d2a 100644 (file)
@@ -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,
        },
index 8e86ec0031fcce10cdec54d3bbb6d03d310daa8f..6a86950699415527261c4d938bbe7cfaca328010 100644 (file)
@@ -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,
        },
index 575bed0836ffa242856ab5db73f8cbe2d80288da..6b0d8b50a305d4a632f6702a7a445c2febdc3733 100644 (file)
@@ -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,
index a2bb8c91ebe6041c61b2789d0ef97b073ac518b1..1b66efd9b728e153506106cf3917b17c73ec87b3 100644 (file)
@@ -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;
index d1cca2831575973dac041b49d066afa404b89f0d..dace827b45d1390401b2f8ae7a0a1fa78cfc0cb8 100644 (file)
@@ -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);
index 4915efa551fca122434cc926adcf92721b58018f..7e4b13e2d12aa84d89e7532f23a9b5053f8c1b2c 100644 (file)
@@ -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,
index bb3cc641130c68ef6d9ce2c51f070abfc1de9e3f..0579daa6221571581d7c869aa7248c86529d7b3a 100644 (file)
@@ -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 */
 
index 50da49be9ae5be7e18a5fc65be87bcfa4b0dabb1..da1cb9c4c76c2e24b46a477a93d6ff1d926d39a3 100644 (file)
@@ -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);
 }
index dbf94b189e7576b6e8a3194c5612b0397e6060ee..9ab01a7047cfe3230bbf41c3944c1ab260887c02 100644 (file)
@@ -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;
index a2f997a9977a7218e1085b9ee75857ab45f9ee44..b5fa583a239a5c978a1af60defe47a61886aeab0 100644 (file)
@@ -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 = {
index 69b51f9d345eda48eff3fa2b85790b70990e188d..5f11ca22fcdefaca7706cb7a81256d16c5894d2e 100644 (file)
@@ -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 */
index 8e64f4862e8517dff5731f55f2fcceaea4642856..110b8ace6d8a46f24cec3225682eb4952e8c6ef1 100644 (file)
@@ -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;
 
index 4507f7088b24c1b69dba253a2968d3bfdc95d7da..6ac40beb49dabea2b54e3de48a9eb721cfc3a5ae 100644 (file)
@@ -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;
 
index b9c9349058bcc9178242fc5680849eb6f074c07c..b1438861d38ade68112572dbec342240a24d9e34 100644 (file)
@@ -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;
 
index 07c07d752fd8978fa040363b10329078c14a0fcf..d01ffcb2b2f5f823033869f24faf1a12b7cc70df 100644 (file)
@@ -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,
        },
index abb0b86c41c942286c2897727e60ab466323d93f..760cbff532105f3bf56485082a43f0e6177fbad9 100644 (file)
@@ -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,
        },
index e158369f5faaa117d23d71878293a27d6a428f86..b86b88da81cd92eb793610c6802ba12c2c13b277 100644 (file)
@@ -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
 
 
index a953d142cb4b41144090cf6f0d66b3ddf382fc67..abfd51c2530ed9172cba8e98fef3714ad4e6b690 100644 (file)
@@ -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;
 
index b7c1875ba90ec2ad06518a1af310fd62d3f357cb..8c5010f7889cbd57192cfaa03d77972f7522aded 100644 (file)
@@ -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,
        },
index c21adb6ef1d5d5b642c375febb1274e40b0cc9df..a7c296a36a177dc5d861216ee129a666c3aa563e 100644 (file)
@@ -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;
 
index e10f027bde03a660899e1a440538c2a661d150e9..662a45876a8b3d9b6e1008173216b32c705776bf 100644 (file)
@@ -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 */
index 556fd6f456e36809af61c5156a062db67f3de386..cdff11d48ebd5b4316584552ca7191e4ee7aee97 100644 (file)
@@ -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);
index 52419959178c6fcad09855b67b417537b70e226a..0275209ca82e33bb4fd0c69569c31e08993a87d2 100644 (file)
@@ -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;
 
index 9d890a5aec5afd5ad9aded994fe247b71644684e..f6c3da0d377d19e5a2b0822e07a1c66cd8b7199b 100644 (file)
@@ -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;
index bab564824efe11ebdf1160e81b568254c3a7fd1c..1ec91246dfee5cdff16bf2b68c939d3a90848efc 100644 (file)
@@ -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;
index 0e6664fa6cd997fe7b64137bd420523beef0444e..748a286277eb28e9ef43a13c1622bd83b6b9bc9d 100644 (file)
@@ -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;
index bc38dd4d071f54cdad06664554d47df099638265..2ca9f2e93139e125925c096f3e6163c3e2cd1c87 100644 (file)
@@ -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
index 88cec6b7dd41244643a6df7b3b7d80e4fb5776ab..7e2025cd6d9cc07a3696cb4f1e038c8b5e3e6ef6 100644 (file)
@@ -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)
index 72321e946cccf6661810559c66a4f3cf69c30ba5..b69a7f8a216ce1177cda7b27a78c99ef5c3ab7a0 100644 (file)
@@ -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;
index 5674cc316530bc3ab0a1b009e7d51b22ff0e3c1f..db2dc835171d2a6bf9ee8d4468ca6e54911b06c2 100644 (file)
@@ -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,
        },
index 394c5d413530cd66fb5b1c1718d55f6b523ece13..8423403954abfae68b01ab7a96e93f0e025d1628 100644 (file)
@@ -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,
        },
index 7266020c16cb3a489a22418fd3b1f32e3dbd9fdb..a1f32b5ae0d1b4131a7ba7b9a8d2366bfd959e3d 100644 (file)
@@ -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,
        },
index c5806f89be1ed8b23e0ad5e0ace6344815bb13f2..4f07fda5adf2cc534d2e52a4c2577ea666c2bd39 100644 (file)
@@ -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,
        },
index 7105c3de1bca98ff5a975d15d2ba35fc19876d98..6eeb8897624b3b25a3e341e765256a4c8964f973 100644 (file)
@@ -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
index bd4149f1aaf45f1f1300563c4aa469d483c2530f..24a251497a1f8ae537aa65de4731fcf1371e8af6 100644 (file)
@@ -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
index 4ec6dc88b7f802a27adcc46ab580630e5c37fda8..7da883a464e327f7880c2974cdb5130770eca75e 100644 (file)
@@ -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
index d010de12335e16525df3219cbe33647262316f7e..8353c77536ac51c0e9ed13ff6fb94732c9e80469 100644 (file)
@@ -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
@@ -4770,6 +4793,34 @@ int snd_hda_input_mux_put(struct hda_codec *codec,
 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);
        }
index 4f4e545c0f4b2ded6029d21851b3443973ea7d23..8665540e55aa7cd1cce19a1cdb405dbcd2ffbbfa 100644 (file)
@@ -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
  */
index 1af86d40eb2396b7dde509052beb8b0180bd0f8e..a5c9411bb3670f7a095e7bc70b8ad0b90a27d4ae 100644 (file)
@@ -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;
index f9d870e554d98d2fabe8791e904d7a393c8925e6..0f3d3db0df71a3110d48643ab0dd214ca0897cd3 100644 (file)
 #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 (file)
index 0000000..7b5e4c2
--- /dev/null
@@ -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>
index 5c690cb873d469af2b419476fb790e893c2433a2..6e9f57bbe6673d3c01371783428287956f8814eb 100644 (file)
@@ -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);
@@ -219,17 +234,47 @@ 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);
+
index af8dd4724da544c85a2b4df431262952dbb39c4a..ec12abd452631d12b9915e0c75a4c45fdbc07c95 100644 (file)
@@ -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 */
index 09dbdc37f781592b45c8e8c03a80b0f133195996..4b40a5e7a8f54270cd9fe1df53d67bdca7c338e9 100644 (file)
@@ -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);
 
 /*
@@ -598,6 +600,15 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec,
 #define get_amp_offset(kc)     (((kc)->private_value >> 23) & 0x3f)
 #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
  */
index 1eeba738666634329d17a76149618c1c6f3e8c26..89fc5030ec792b97204f5d296571d7280669bfc3 100644 (file)
@@ -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) {
index 3bcb671723583ed852ec97aa844d2736ffd4b330..a2537b2f87240ae20f2d75d5d3cb7a0ebdc81510 100644 (file)
@@ -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,
        },
index 03b1dc317ff0341122d48a0535e41963b2834157..60890bfecc196600ffa15ab5979c06aef8891f9b 100644 (file)
@@ -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),
        {}
 };
 
index 71555cc54db1686519b8bd20f168d4fe5babbcad..0fcfa6f406b8ac8738ba466954cfe7a6bc6faf87 100644 (file)
@@ -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);
index ad68d223f8af9e7dc43d24af303aab1eec64ca3d..7743775f6abb34b3babf5a1bf44c3b1f5ef308cc 100644 (file)
@@ -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),
index 9ba8af05617080f8081a5a69d68bcaec81cfb847..df13c0f84899773e7b40f3b25a23ffe60943fcb6 100644 (file)
@@ -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,
index 019e1a00414a460cb7a43c8c6bf142ecc2f01d38..09bb64996d72ee3dba0335fa07b2cb3bf44fa2a9 100644 (file)
@@ -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 */
 };
 
index f7ce33f00ea5eae767e4e14732a6de8077bec841..7e50c1324556df83e7dbb2f3cd8a7a11ed5eb7f4 100644 (file)
@@ -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
index e525da2673be3c5a4b12de44eb7c81e6ccadfcdd..2f9b934678673e077657436b49127cc15d5b7045 100644 (file)
@@ -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",
index 20bcddea2eab19320d25299180368a815bc4f90f..55902ec40344d824b17d56d37d047f79281ba294 100644 (file)
@@ -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",
index 20c6b079d0dfc33cfc4620006bbbe944e39e91b6..9e28cc12969b3632357ae4f198634da499864903 100644 (file)
@@ -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",
index 6fe35b8120400ddb8c073f9166879b9821984a33..bc2e7011c55d7fa184b63197f82ea7d6fab00a95 100644 (file)
@@ -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",
index 6914189073a4d11ad81194e5cb7ad91c0a59e7da..59e37c581691e4e2b9072791956c4fee2ea09771 100644 (file)
@@ -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",
index 5be2e120a14e25a03744b873e690f765eecb9545..2ffdc35d5ffdca6ba5e1d1587feae59e6d08beaa 100644 (file)
@@ -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);
index d0e7d87f09f0ed4947462630906ec02249e583c6..b209fc30b334b455c7a83701f1f5b398de4881e4 100644 (file)
@@ -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;
index 245d874891ba25c2d993ea9de44536e0ab27ae6e..ce70e7f113e0545f90e70edfd363271b9455dc58 100644 (file)
@@ -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,
        },
index 14fd536b6452d6e5dda1ec01f12929a89c4cd7c0..8855933e710d7fe54e60ddffe6e509558f9b4589 100644 (file)
@@ -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@",
index 726fd4b92e19e8d564adef229c9c5201a0785963..63aa39f06f02be728081d77c8b5c7d7a32ccdbd4 100644 (file)
@@ -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",
index de29be8c96574e8bd89eacf81b9aee5eb8a51518..0011e04f36a23bc08dbeb8fbc2af4ead158ed69d 100644 (file)
@@ -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",
index 92c1160d7ab52c52811609008ce9cfc6fbd54c18..5555eb4b2400696e640422aba6a231f0a47e43a0 100644 (file)
@@ -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",
index e36ddb94c382932a4e5c9b35095678d3b9c90ea5..e610339f7601416c972364192011e4f176819727 100644 (file)
@@ -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",
index 7bf093c51ce5a5569f6cec1a1f9e53a88763236f..2261d1e4915004281d3fcce7b29e243faff41689 100644 (file)
@@ -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 (file)
index 0000000..302ac6d
--- /dev/null
@@ -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 (file)
index 0000000..858e5fd
--- /dev/null
@@ -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 */
index 1948632787e6be6e97e4cac092695b89d55bfa32..975e0357bd5a047bdf54faa4970e76a42694bd89 100644 (file)
@@ -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",
index b508bb360b97d1499eea3902cade76ff83f4b3f1..7641080a9b5d33bc853821a135eeca9bd62ab84d 100644 (file)
@@ -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",
index 69673b95869da9bfd855aa4aa05acdf24f4c6835..ffd894bb4507b2ea919b18f980c09007f6a8f8bf 100644 (file)
@@ -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",
index 4c551e147c089d8186db424d6bc630ddeead58b1..5dbb867e642cbfb955a89f4a7ea8cb3f8fefe48c 100644 (file)
@@ -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 (file)
index 0000000..8072ade
--- /dev/null
@@ -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 (file)
index 0000000..c119f84
--- /dev/null
@@ -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 (file)
index 0000000..a3c05fe
--- /dev/null
@@ -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 (file)
index 0000000..93a2d69
--- /dev/null
@@ -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 */
index e618f789026ea7dc4ff2ddddf4fc46a3e1328a39..bcf30a387b87640f2f42202b1189af0fde49066e 100644 (file)
@@ -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",
index ea4b706c8d635925c248bfb497a021361d990a27..3b9be752f3e2f8cdd5c9c248c1569a94446a49e9 100644 (file)
@@ -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,
        },
index 4d551736531eebe546e4620768907e6775840ab2..fea09e8ea608d0078fa84e8fa81e73e40a33802c 100644 (file)
@@ -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,
        },
index 8a67ce95f2468395a65474f8a7de194241570c35..43b4228d9afe41812a25d4d9ea81e2b028016410 100644 (file)
@@ -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);
index ac15166bee6889477d5cc4c005adc8979c6b7ee5..322b638e8ec48056c7e433f2067e4aff80bd0014 100644 (file)
@@ -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);
index 72f8ef0ac8652900119c8a8eee4a8788ecf4068e..eb1d6b97df164f20517222be0173df1e792dce1b 100644 (file)
@@ -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;
index 6b8d64812951a1c15626ef9ed37c731ee9dad502..52c8d6b0f39b9c7b35183f89642a816d8cdd7e58 100644 (file)
@@ -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;
 
index c44db68eecb57b01b95d01eb4d8e92e9495d7f14..5ea85e8b83ab5018029d92504902775170adb018 100644 (file)
@@ -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;
index 9d7daf897c9d2f5c474e5eeaf6a47e21a23c5f1c..04df83defc092c52723cac488ca972737342e425 100644 (file)
@@ -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;
 
index 5579b08bb35b6337c646b6d2cb6be5215f0d01d9..298bc9b7299116b23a83e572c69cfb3224124351 100644 (file)
@@ -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);
index 8c3e7fcefd99c91c38d39f92fd0cae8323cee210..633c8607d05374c7995d4a61af918d9f4b99eca9 100644 (file)
@@ -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;
index 4d7ff797a6468abf5b5499cdfd92dab430d9948f..5ec5e04da1a5a02f2008b070c76e24fe3964765e 100644 (file)
@@ -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);
index eb3cd3a4315eff8990b7f2d7162a6aaa640d35e6..9387533f70dc36c9d6b7cfd5498ff6a468fa09d8 100644 (file)
@@ -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,
        },
index 0762610c99c0e7046f490d0d71e9a304a9e940c7..01f7f37a84101dff11742a415ad607a9ac2d095c 100644 (file)
@@ -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);
index e0f4d87555a04ace24920b66fe96bf8994d6e111..ece1f831c16a834c8c0806ea5d5c812bc257f24f 100644 (file)
@@ -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 */
index e80e9a1e84aa4b8cd6ccfaf12abe49de0b063343..563a193e36a3d84d65998c45fb0fb0b5279eb532 100644 (file)
@@ -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,
        },
index 2becae155a48d2f0c49bcb999194bc61a469e139..ada6c256378e18660061c59c37352785314b41f8 100644 (file)
@@ -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,
index 3d71423b23bcf5450b2926c5b900fa76a91a8559..64b9fda5f04a71f4d0898d083468a6ed94437d8f 100644 (file)
@@ -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,
index c8febf4b9bd6e10c9763c989ee1d059486f019bc..d231b93d6ab5443604aa651ff859e266f7d6a60c 100644 (file)
@@ -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:
index 8433aa7c3d754064f9e0b57cae437277161f09f5..c8c7f2c9b355ae8f4dde5d8deb4b68a11a64f296 100644 (file)
@@ -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:
index 63cff90706bf1749b9b7154f1c6ec81c903f68fd..6ce68604c25e4834460b3c0533e8b1eaca511151 100644 (file)
@@ -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;
index be4f1456009a55ea33d5c8597da0607fc4b203a3..b97384ad946dae84ec724f4c91d2b46a226b50df 100644 (file)
@@ -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);
index bf207e317f71864ad2dc35b4003be764b81f5c39..d995175c1c48c44960071683fd03aff64d260b42 100644 (file)
 #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 */
index 7d291542c5baba8803cbc3fddae2d33121e2f3d0..63c1c80415541c8a7207ded0c1cab82e8fb952a2 100644 (file)
@@ -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
 
index 46b3629dda22d3d9fbd33f281b2dc13c79815f56..2450663e1a189c84d4def85589a5c220d99133af 100644 (file)
@@ -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);
index 9b98dc406988386b62a6c9f07e31181f98d2bb29..5fb88ac82aa93f6f4f0d0021ba0775ebf952e1ac 100644 (file)
@@ -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);
index 0d6930c4f4b7bc4c2d4cecd0a074cbd30b3305bb..4fae81f21efbd25a1645bf25a5b296580b4b8d86 100644 (file)
@@ -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);
index 748e36c66603a7f9928f70a6f13ea8e64b875f76..6e02e064d7b43df1159554899f1007a9f223bc7b 100644 (file)
@@ -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);
index a15fc100ab0c320808229729d00c4a55eb1d7da4..773a67fff4cdeb64469170912e82034919e5a841 100644 (file)
@@ -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);
index 51e43407ebc539f657b6d7da9ab3647917f2e8af..d59abe1682c58f9d394340d48c38e1860f906e89 100644 (file)
@@ -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,
        },
index baa9946bedf019cb098032be10ee5df4c233cc05..a2e7686e7ae3300f78240db2755fc23899ecec30 100644 (file)
@@ -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);
index 8a6f1f76e8709508cb186a4957ad2776e2865392..1aefd6204a63f26347f856881b3522d00e37e169 100644 (file)
@@ -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,
index 06b10d1a76e56c3593e09f704ba5efb3b6688577..fb0e1586a6f87cc25bbce39a64744e1fea468de5 100644 (file)
@@ -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,
index f0b4efdb483c3ea627cb8a544b9a8b9c6ff2bc58..6442f611a07bfc0d907dcfb1dd1b75c8aff1d2e2 100644 (file)
@@ -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,
        },
index 8e0efc416f22f74bd68ba1f1fa89565073ee2bb0..4f5fd80b7e5688ef008691f908e4b781b5d186dd 100644 (file)
@@ -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,
        },
index fdfbaf8572336ddd31648a127d668701d60b0a28..e2f1ab37e1548661dae8f8cadce87764db7d52d6 100644 (file)
@@ -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,
        },
index e01fe34db9eca55ec0feb02082b5f25b87917b62..01c49655a3c1014bb9dec01784971b6e8a4d250c 100644 (file)
@@ -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,
index 3a6f03f9b02f6bf9645dd3f473396881e3fed1ad..22056c50fe39fde10184856c33e14d20bf1743a1 100644 (file)
@@ -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;
index b36679384b27b6ab1486481d15a6e779c9c6a126..5fbf5db2543d40c531efdac069df3ffd13b8a2a8 100644 (file)
@@ -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;
index a9d350789f5563a22f1f3184826125599ef8b36e..0040f048221fa39553ab35398a3d872101bb306c 100644 (file)
@@ -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;
index 00e2d5166d0a2fc277da60e02bebb1206608a5d3..cb4f0a5e984e9572ed47e433715db7f047753fe5 100644 (file)
@@ -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;
index 24200b7bdacec5a74ab335fbb4ec0fc78062d2d3..b86526223e4e96b3939355f1f12f995c7c822a26 100644 (file)
@@ -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;
index 4080becf4cef0f892d453143b517dd23df46f59d..01aecc2b50738353ad8a96f618c01be631981240 100644 (file)
@@ -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;
 
index ab96cde7417b833d6e9e14e44aea7cb91cf965ba..c93fbbb201fed94645cf9819ec2fcf287b3389fe 100644 (file)
@@ -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;
index 210cafe0489020ea970ac2724a68797a5be23a6e..09fc848d32ecd475951f09513e492e78a03d2a1c 100644 (file)
@@ -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,
index 9b18b5243a56a74bc704fc3e2c79901ac8ec0079..8c7dcbe0118dbce433c0dd7850f5ad467d90a8d4 100644 (file)
@@ -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;
index 9cea84c3e0c65e8d557618a4f82ecc2aa97d06db..b23354a4ceca7023d99cee8da266d0186c0dd208 100644 (file)
@@ -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;
index d48b523207eb979b8dc034e3ea7bcd92cd304179..e59a73a9bc427602717633ea66953a73950d2d18 100644 (file)
@@ -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,
index 0a3394751ed20c3d0d352077a30be7d107b50657..e68c4fc91a0304002537845b4a8b1182ab107258 100644 (file)
@@ -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;
index 72b09cfd3dc367d4aa28826e750e27aa2ffb1885..d1b691bf8e2d918cb3e8fd97e61cce74c464cd76 100644 (file)
@@ -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
index a5c0bf19da78f01e823fc614c61528c30272a67c..41967ccb6f41e3968753d4922ad03f2439ad81b9 100644 (file)
@@ -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 (file)
index 0000000..30184a4
--- /dev/null
@@ -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 (file)
index 0000000..6a293c7
--- /dev/null
@@ -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");
index 9b84f985770ee4e09ca1d7a8ab04cbe410fda037..e99f1811300aef179a5c1d5c33dc702249175681 100644 (file)
  */
 
 #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");
index 5e0a95e643298b8f5210e7619139b48a02ae939f..bb45d20e7250aeace79a2595f5f9676349ba05d9 100644 (file)
@@ -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 */
index 354341ec0f42f1129adbaaf310366af46b866229..1c7663422054049265957743bad8c6f8678e9e17 100644 (file)
 #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");
index 5d4f0f9b4d9a875eb935ec79488b76ff17073ab0..b1f08d51149526006021c7314aa4f3e15847de3d 100644 (file)
@@ -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 */
index c88351488f45c5c6adb0529a212ab257531a90fd..da976291da9e28c46c55f45ff9ba70ea52544181 100644 (file)
@@ -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");
index c5ac2449563a5140524702c5db367c5a2f52bb5f..ea7d9d157022a59be25323d071e3993bc0b98799 100644 (file)
@@ -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)
index 511d83c11a9a0e2799688df405a590ebc0a19ac4..376d976bcc2da652d9e047f561392b1915fcbe8d 100644 (file)
@@ -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);
index 30ea513d81d730cefa1027be46726a1c69e8df5f..a497a0cfeba153aa70630b0dfadc7e69bf2d0e7c 100644 (file)
@@ -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);
index 8372cd35f0d6bea6701df54c829037a89c4e67cc..3b4eafaf30d3177d223f1a28c4374e55d32e8e68 100644 (file)
@@ -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);
index 0a91b186a86f1baaceae28f921058cf5c72d3e9e..befd1074f9bdbd9b008dc6324b5669a7f8a549c7 100644 (file)
@@ -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);
index d4b9e364a47afbeb972f82e1605c9d67566564bf..072448afc21993a1e772cb71c078ce2fc07dd735 100644 (file)
@@ -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);
index 476b79a1c11a764e4ea80ab484ec4eb8a16701a9..6ba07e365967221384760d2917bc1b8850ca5895 100644 (file)
@@ -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)
index 0607ba3d925831bb79e0221942256e8dc2c191fc..360b4e50d7c836eccac7000f3216cb61d3c9d146 100644 (file)
@@ -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);
index d7dc9bde09760ce5bc44fe6bd8bf0f4b79843a4d..7e2f36004a5acd605f9223e93d168143e11bcd25 100644 (file)
@@ -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);
index f4e9dc4e262e6c63a6a5e1cf318c4b58cab3b431..8e41bcb020eb5beba44505b7df5c1cfae0ee64e0 100644 (file)
@@ -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);
index 16b9c9efd19a79aba78c8e01ec9e4095300501d6..d23f4b0ea54f3779f9e655ef7e7557c8e8671f26 100644 (file)
@@ -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);
 
index 63205d723eab769f8ddb5b007bc2d85cfb484bc4..262c1de364d87a06ee43125203e18d54f26a968f 100644 (file)
@@ -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);
index 4dccf0374fe744fd54aaf379caf92e3eec5feda6..168d88bccb41cc18f18b22e41296783e9fb17ad8 100644 (file)
@@ -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,
index 254490cf1876a4234edc363b743cf06aa966fb27..0e6b888bb4cce6c7a44c79d49c7b284692deeea6 100644 (file)
@@ -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);
index 594f88217c746e0f8639988b9851c105e2f5c0e5..c1e516ec53ad174c2c46d0d6735f9e96d2205915 100644 (file)
@@ -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,
index c3c2466d3a4214a220d21a72add7376760a6fea2..8f337972f438f155daffe7cec9bb5fe8405f9748 100644 (file)
@@ -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,
index f3adbdbdd5e1a0a96f93caf305c6ba0a74619e2d..4ef9683bcad89c95906c5bf638ea2b73fc08edd6 100644 (file)
@@ -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);
index b0531fc9d814058409b5cf585e99eaf0e3f7352d..3b55081a96c0f83bf63b10e031964ff42e644734 100644 (file)
@@ -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);
index 84b09987b7f319cbaf01e2cb05be11c666404280..3b1b61a4481571960bda090c7342b2a465a7f9ea 100644 (file)
@@ -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,
 };
 
index e01cb02abd3a91e17cfc9b3e22ee1df563feb22b..5db68cf7b281ab8fbb2af67310b01e7f75e4612b 100644 (file)
@@ -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);
index c3521653cfd3fcac901fbcf076752b5b10c654e5..f3f50e6fd6eb29218f622664b37ba7065946b57c 100644 (file)
@@ -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,
index ac4a7515e7be4d5e417d17eec041b3b1151c4df0..3365d4e843b7382a663380bd9311bdd762828be0 100644 (file)
@@ -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,
index 665d9c94cc17ebeca825898ebac89f5c04937dd7..72eb7a49e16afb0a52e668aa41d1e85994c97092 100644 (file)
@@ -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);
index dd997094eb301f8134b0b11db3a12ac6ed16d782..a397bb0d8179650e60967ed65fd4e02665940e6c 100644 (file)
@@ -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);
index a193cea3cf3cc73406a201db9e5aeb10b7772cc6..9d77fe28dfcca9bbda6b346a4e33af7c67154709 100644 (file)
@@ -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);
index 9fd3b6827bba91c6717fdd9a006cf8612ce81d18..60159c07448da792e62e8e68f61e7d48d7ec04a4 100644 (file)
@@ -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);
index b92759a3936157e0884b98f752935ccbef7b8945..3a847828932ae01e13b2be5ca8f587c0048f17eb 100644 (file)
@@ -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
index 9bd4d95aab4ffcecb9abf5bff4e0c94d7203adee..f6e8e36cceb77b60d5c34fc5bec54ece440c6653 100644 (file)
@@ -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
index af547490b4f7f6e0b1dbada793259c64a513a203..6c12ac206ee9ab8f2d4fc018c22e3e45bb2365d1 100644 (file)
@@ -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,
 };
index ea06b834a7de45c216e8922927a7aad892be411b..ef2ae32ffc669849bbfb791eb657ed4ff2501497 100644 (file)
@@ -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);
index dce6ebeef4527cfb176063e91c90a9a741ee3f89..9a92b7962f41b67e3ba8461d1a88c584ef4822b0 100644 (file)
@@ -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,
 };
 
index 2f752660f6789760381aaec5f0391aac94b33bde..aea7e52cf714117a445347cbe528f6732d2bd662 100644 (file)
@@ -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
index 8c39dddd7d0063d90adcf587c5e6dc19c37f73ad..f385342947d33317118d924fd5a88c44e3b9532c 100644 (file)
@@ -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);
index ee7a68dcefd2442b1650b16395025bc2eed39990..b1f2baf42b48233678ae051bea1bd2b9fb747327 100644 (file)
@@ -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);
index 704544bfc90dc564c774593ee7d0300098c47d6c..068b3ae56a1767c8242ea9b454f15ca7f045dcea 100644 (file)
@@ -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,
 };
 
index 51f2f3cd81364658d0b78d48c7baddb7cac5abd2..dafdbe87edeb56d82369db5f310658a25298ee17 100644 (file)
@@ -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,
 };
 
index ebd7b37b902bb4019dee2059a633c120d20cc4f7..3c839cc4e00ecb48a5e3948567c14dbede7706a3 100644 (file)
@@ -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
index 8103b938b8c001214858e9a628ae60908424cde3..506d474c4d2227372b6b8e4a6743ca8f67ef7da3 100644 (file)
@@ -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);
index 31d4483245d0db951584a0e1619b91c8ac8fa726..6f6c335a5baab15d93466a212cc63d0b71ea7197 100644 (file)
@@ -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);
index 618fdc30f73eb3889f2372e4bba9033d3675270d..684fe910669fd884f04e3900c03fc3631773e821 100644 (file)
@@ -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,
 };
 
index 543a12f471be65a70c9b88a529c9d2dd42f8b7ed..5f9af1fb76e862a1fb2eb4e73176d47cccf4aef8 100644 (file)
@@ -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,
 };
 
index b3e24f289421a7fda3dda11043039179c4777535..1f0cdab03294725b4ba02f6a28e4b6ce68eb6e89 100644 (file)
@@ -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
index 2b457976a7bff0f18ada9248acdc0c25b4bd82cd..25bdf6ad4a546c16363381a1a4922c4a334ea48d 100644 (file)
@@ -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,
 };
 
index 1960478ce6bb883dbf02af92e242e2b538ea8823..256c364193a54ea6864adbf79640b3480983285a 100644 (file)
@@ -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,
 };
 
index 7dd02420b36d3976f21b86ac8e50f0af0372a36f..f2e62e45f91288916a252486a4ac130c5d7dd022 100644 (file)
@@ -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,
 };
 
index 054967d8bac2f6d089214e390b1bd6ce416f64b2..adf397b9d0e650eb19768e7bc6c592352014a595 100644 (file)
@@ -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);
index 36ec64946120077455ab218c85aef34eaa29ef9a..41dae1ed3b714a4734448b1d3c99938af1fe9d9a 100644 (file)
@@ -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
 #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];
index 064cd6a935163ebf4fa0619b80f67154e1733528..23316c887b19211f7c7473767b956895abda397f 100644 (file)
@@ -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);
index e3f0a7f3131e14b7895aadf2daf8bf81f6058d8b..4f1127935fdf5f9578970b13fcf73b8815d469e5 100644 (file)
@@ -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) */
 
index 97a81051e88d125c9937057e3b51324a7bb0f9ae..99bb1c69499e42a6791ae12c55dde2d53efb7f49 100644 (file)
@@ -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);
index 2c08c4cb465a1995b5b8897c72fea887dcdfbe80..a0791ecf6d95e64514b5320717b586f83c32d7ac 100644 (file)
@@ -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,
 
 };
 
index af5db70805199e81b06e7d48a8e844ae504489b2..9c12314565024fcb80d5091a6fc57a6dddf0555b 100644 (file)
@@ -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
 
index 01be2a320e21b71b1932a95d376031b943200129..dc0284dc9e6f85dde0fa61819b5e86145f55d608 100644 (file)
@@ -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,
 };
 
index f379b085c39204dfeb2a6fc34d7c07d9f15c9f0b..fc9802d1281dcad0d8ba57ea9d62a02322b5864a 100644 (file)
 #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,
 };
 
index bfe46aa90362fe262b7894d0bd9451ad3042f23f..4f4f7f41a7d11b5fa79245f06474d27d54fe3e47 100644 (file)
@@ -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);
index 3e929f079a1f0eb4b3fa472482d68503703da8c4..66967ba6f7576c8f1fc816bb7e894f3e7799e3a2 100644 (file)
@@ -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);
index 1bf55602c9ebf2ecf97ca2912a99815a5e707493..53b455b8c07a76dfabd63e46d2ca934a418061bb 100644 (file)
@@ -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,
 };
 
index 85d9cabe6d555d9e28e3812f1d97f631434ff461..d991529e1aff1a021210b8887a35b2b609601130 100644 (file)
@@ -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>
 
 #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)
 #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,
index 81a328c78838250c952609275af6888e875e6057..9f9f59573f721344995233da13ddf875f43436fc 100644 (file)
@@ -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,
 };
 
index 99b0a9dcff346ac68b3915ae320b60645cb6a01f..d75257d40a496d26e9bb513f6fd000abe6f13a76 100644 (file)
@@ -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,
 };
 
index 17b3ec2d05cb1ebade50fe27eb95b4a62dfbfc20..a6ac2313047def253ddc0ff4ebddde4947803c1b 100644 (file)
@@ -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);
index 3264a5169306fc3f8d769912173f803fae3d17a4..a4c16fd70f77546450851951245f803ec4bf004c 100644 (file)
@@ -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 (file)
index 0000000..c9772ca
--- /dev/null
@@ -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");
index 38d43c59d3f4cfbc67cc11f2d86af73f8ae910b9..41cdd164297046c3045c9463ab6183810e02a126 100644 (file)
@@ -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,
 };
 
index efe535c37b39eb82f110e76328f3345fb3fdd10e..58c38a5b481ccb7658a8a6a285d5874d13659d50 100644 (file)
@@ -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,
 };
 
index d15e5943c85e931bc0ffd5472b27768bbadaeb79..6b6c74cd83e2bcc2d9e5292cca7c2b70618eaa18 100644 (file)
@@ -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,
 };
 
index bc955999c8aa56c15fb30e99bbc8a7eecb930a67..5402dfbbb7162f668d8841a83ad3c04db5d2516f 100644 (file)
@@ -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);
index 96aa5fa051609357cda4555e52bd4d4b5b509909..26118828782b9b5b4ced3c372ccf128b971cebde 100644 (file)
@@ -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,
 };
 
index 1bf5c74f5f96e2ac601f300152a1d670bc9af92c..529d06444c546711c1fcbabffbf75c660486ce1b 100644 (file)
@@ -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);
index edcaa7ea548757b3825acb27a1af9fd958d9121b..f2a6282b41f4e07a1627463222b4ba9d091a7cf1 100644 (file)
@@ -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,
index 960d0e93cce9463a3592c17d74de0f9d5ad4bf19..912c9cbc27242eb48229506e86b3295a81967185 100644 (file)
@@ -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,
 };
 
index df2f99d1d428940424d419378ce6cf9d82a937bf..cb1675cd8e1c5ffd9b404b9d12ee9c404f6f2efd 100644 (file)
@@ -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 (file)
index 0000000..f2d61a1
--- /dev/null
@@ -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");
index 50dbdb9357ead627961f08a170d8430b99faca07..d1ae869d3181b1ddfc40f6fc8c4be9c67272d583 100644 (file)
@@ -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);
index 079066fef4255217adce5319e58be0d15acdcb91..f8d30e5f63714c4d58154b0bffebeee424b11dbc 100644 (file)
@@ -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
index 0935bfe624711646e622b0637ccd56484dfd115d..cfb55fe35e98691cbaf7b18404b93e02c1cce73c 100644 (file)
@@ -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,
 };
 
index 9e31448623866e9e7665b289bdca1665b4924db2..ab355c4f0b2de0aa786e754360a6a877a0855756 100644 (file)
@@ -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,
 };
 
index 982e437799a8e62aa8085a9d5b509fa4d8f8a387..2eda85ba79acd2cdd442b78fa4631542f0caffdd 100644 (file)
@@ -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);
index f230292ba96bbfc0c5cf7c7264dd4435de3d7590..17df4e32feac401c551ffef564dd10c25ae6bf49 100644 (file)
@@ -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,
 };
 
index aae2b2440398aaac19a62eac62b6e7788e41035c..35774223fd91f2a03c4ce4ed56c45df3f3ff2a3d 100644 (file)
@@ -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
index d2e16c5d7d1f71ca5d4425e7c6d8a83dc7bcb7ec..782b0cded2e69350046d942cfa67c836e521ce1a 100644 (file)
@@ -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,
 };
 
index 565ff39ad3a35ced5598c9532bc33b85f1d8983a..8d75aa152c8cd29dab7133791db83955d5a6bd14 100644 (file)
@@ -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,
 };
 
index e7f608996c41e1292c6a00efc56935b9acab75af..63b280b060359f12ffda4f018f4f9e012f32eac2 100644 (file)
@@ -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,
index 00b85cc1b9a3508f8db9a677bac90d4e2af50038..3fc3fc64dd8b47a85ca142d3ef95dfe637908754 100644 (file)
@@ -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);
index 6c3d43b8ee858538346565ec5915f4b2acf004d9..6d0aa44c375755fb8715c2089d27d4a3686598f1 100644 (file)
@@ -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);
index 2502214b84abe918514f9462039ef1f941bb3f59..fd0a314bc209a4005e8b3488930b6b7d3215526f 100644 (file)
@@ -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
index 7b24d6d192e17d8cd5b61ade0d59988dde07c924..54cd3da09abd036471291901461331231ce78ab7 100644 (file)
@@ -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);
index 99afc003a084cabfc47511047247c0416da8931f..ad2fee4bb4cd12ea133e9a455758a6d9a921d4f7 100644 (file)
@@ -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);
index 951d7b49476a5a04d6e04447801be14963fe31e3..6e6b93d4696ed9ec85e6502eb1c1a7cabc0fd63a 100644 (file)
@@ -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,
 };
 
index 683dc43b1d87898508b011e7ca4aee7087049f7e..1cbe88f01d634137e0d7e85218556e1c81710d59 100644 (file)
@@ -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,
 };
 
index eab64a193989ac2917773a4df7613cbf644dd58f..afcf31df77e06efe19c709630f53990741348227 100644 (file)
@@ -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>
 #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,
 };
 
index 7f567585832eae40c9ff03b33a49f0612427c877..5a5f3693623568d2d6268e9bc10e7055664c5d3d 100644 (file)
@@ -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,
 };
 
index 7394e73fa43c0e526e7ab4e83480fb89bbf9891d..688ade0805897557baac586aeb6387a70361fd2c 100644 (file)
@@ -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);
index 9211e4192f710b305ca46420e0be64037a0f6967..ae80c8c285360cffd1ef82af06626ceccf2769d2 100644 (file)
@@ -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);
index a4cae060bf2626de702f88c4b62dee0e3f110860..fb92fb47d636c1a92d04d1633b9aacf2d42b31d7 100644 (file)
@@ -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);
index 5d277a915f8180a4a5b4bc301ecad54d7b7c6b9f..af6d227e67be02f72da11eaefa12a97d2fcd8c80 100644 (file)
@@ -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);
index c12a54e72e891d071a51e2c4d069c006c6a9ff18..6ed5433943eaae4716f54a75f7b4cf4d9fd83fc2 100644 (file)
@@ -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
index 8d5c276735012361cebb34f24dd123f0564354a3..139bf9ac94078152470fc639816a328eac8dbfa6 100644 (file)
@@ -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
index 8b8bb70f1eb959e5ef3a762e88ffce716f75107d..5b428b060d418da78286a605060c4cb4c019801b 100644 (file)
@@ -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
index e81705620718eacf785fc10ecab3d74a0adbebcb..462f5e4d5c05ffcc3c4876d35bca320ff1743afb 100644 (file)
@@ -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);
index 00a12a0c3919b12e1cf325a84d82bec1031e9b04..c6a292dcded0c11eda10c5dfa8fd70e2be84ec0c 100644 (file)
@@ -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
index bb1d26919b10c1ce05553317ede7a25c05c4e006..5276062d6c79fa59d0c2c0992a5f9b52993fa156 100644 (file)
@@ -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
index 5c9634f4c1f054c00d7e69f3d1e1c67041be6b99..2f167a8ca01b507cb3b61521de5db174b186b073 100644 (file)
@@ -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 */
 
index 4281a08021384d30f0eb4673e9298f5e862f7d86..b18813cc7ba9f06c87b399834abbceac5d3b9f49 100644 (file)
@@ -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 */
 
index 89151ca5e7766b69cd57447e611fcf1301fd301f..50d5ff616232676bb094054d44a0c1076ddba0ab 100644 (file)
@@ -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>
  * 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
index 2e4a775ae560861543f9d2d1bb74aef096e5181d..0a4ab4c423d123f0bf1ce0e16ed6d261c4b5a52d 100644 (file)
@@ -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
index c7c0034d39669a5e4b548bd7a46f40eb716f00cd..89a18d82f303e168f874a418840a9d33a4923910 100644 (file)
@@ -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);
index c32249ddb2e025c4cb457095f47524b4e334424e..f31017ed138128badd671cf851a029d5171ae7f9 100644 (file)
@@ -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
index 3fdea98f732ec3814dd96f2150ffa5fe4c6b4349..f1fdbf63abb4f41e4e8c1a69b92e1357f3d6df00 100644 (file)
@@ -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);
index c088020172ab66e25bbc8e0f30f554b77debb202..d321a875b029dc693fb2b7483dd73ceea1ce4ee8 100644 (file)
@@ -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
index e781f865e5d7673d3fd2caae65a6e69d201e9ae6..7c8257c5a17ba5f591cd408e63ff2912e7ed49c7 100644 (file)
@@ -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
index 839414f9e2ed3866d41f09c96cd3d50ec9dcc045..134e41c870b9a0077ae364eef131e471d15c96bf 100644 (file)
@@ -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,
 };
 
index 7c8df52a8d9d3710e11d87d352bed367a81c4920..3ff195c541dbf839e946e036f1f314aa27662f38 100644 (file)
@@ -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,
 };
 
index b20aa4e7c3f9c2f85f84deaddc06aee763061987..b1591c61c254ebc1f12d0a19e682e45df632ed77 100644 (file)
@@ -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,
 };
 
index 2f1c075755b1fc7dd4827fbcd547da0556e9e2a9..82c8ba9757202402cfe53e44b0a7dd587df502b5 100644 (file)
@@ -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,
 };
 
index 00121ba3659718ab4c4af6ff5135373762de4765..b0710d817a65964dd5418502e366f310d36b6dd7 100644 (file)
@@ -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[] = {
index f0f6f66017859c7e8b5fcab1f470565d8a6cdd88..9bb9273259937770ac4f8b188b05f803a1079121 100644 (file)
@@ -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,
 };
 
index f387670d0d7591c1860c071087c81736974e9fc5..900328e28a1596cc1cd189185f18460113de440c 100644 (file)
@@ -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,
 };
 
index ce6720073798ddd352df483182b1653b121ec096..bd4b0db4cdaadb11fe12caed12b8e8e2f5bab7b1 100644 (file)
@@ -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,
 };
 
index 5ce6477584438b3a8555bada53f8e17c1dd7cc5e..67aba78a7ca5d8de561d2a3c70a0f5a6e4307f7d 100644 (file)
@@ -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,
 };
 
index 9a39511af52ad180bda356d210a7594de1c3f80f..ea58b73e86b28df311fda7545463089b90e89b6b 100644 (file)
@@ -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,
 };
 
index 4c0a8e496131c1cc2bf9933605dee7664928520d..f347af3a67c2d2d390e50d523b33cd3372530b1c 100644 (file)
@@ -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,
 };
 
index d8879f262d2762dcf860db46388961ed84063f33..9fe1e041da498cec9bc335959c92d569ca0102b9 100644 (file)
@@ -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
index 14f666398d0c9a0bb7677fa6a1bdbac43125c0fe..ab3782657ac81e7ae11afa0142e1d2d5a1e4d483 100644 (file)
@@ -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
index 1d4c5cf47b06ba24d49509d904b5460e3ad22891..39b9acceb595185d60821270073d9e5895305baa 100644 (file)
@@ -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
index c28c83e5395d93d76288bebd356df1abdf791f49..837978e16e9dc85150b96ed5b8671cd569138e38 100644 (file)
@@ -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
index fe439f027e102b9274883a9a879dc5cf320bb6a1..3a39df7a38295a36a28d7865405cb7c0096089d1 100644 (file)
@@ -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,
 };
 
index 94737a30716b7acf9fd47382b09f461c6a5ffec0..433d59a0f3efa025598cf5c63f42640120893f90 100644 (file)
@@ -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,
 };
 
index b2b2b37131bddc4acfb8fb0e51a9bba220da9907..3b269fa226bdabec90e97c2b77bd8347909a9df7 100644 (file)
@@ -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);
index ccbce5791e95829b5d98ce472ac50d922e6e4703..45f192702024485fa23e87567eeda19bf0080e22 100644 (file)
@@ -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;
index 28c89b094c6ee6a5af57bab43a4a7f1c7d84f1f7..90a65c427541fb9290616379f7b53bc17c01d0ea 100644 (file)
@@ -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
index 6dcb02c3666fc4e37f6763aa977dec746c15cbe0..46fe83d2b2242610799180edd6774c0dc3cfe674 100644 (file)
@@ -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,
 };
 
index 2de74e1ea2259ae0750d90d0f3e769698b43469a..630b3d776ec27133cd54f2c3dd440ae304c83417 100644 (file)
@@ -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
index c7ddc56175d12ad799f449a814db1432d341305f..a07fe1618eec439d3ba001573331f4046b4e2095 100644 (file)
@@ -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,
 };
 
index e8e782a0c78d0791b88d509ae5fa33c9e6a77840..05b1f346695bce8d10c7e406ed6413a744117102 100644 (file)
@@ -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);
index 4dd73ea08d0b51287c8a394dd269798fc5dc8b06..8e9a6a3eeb1a257886415be532a186a1900de1e7 100644 (file)
@@ -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);
index 3eb19fb71d17209e0bccc071ed3f481471201276..f7afa68d8c7fce0a119eb98810e969609e28e225 100644 (file)
@@ -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 (file)
index 0000000..ffc89fa
--- /dev/null
@@ -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 (file)
index 0000000..ffd29a4
--- /dev/null
@@ -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 (file)
index 0000000..5632ded
--- /dev/null
@@ -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
index 6fac5af13298ffa2c64ebf5bad1b5fde6a0ac6f6..d55e6477bff0c9a855379d26db50538ff7b5e178 100644 (file)
@@ -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;
 }
 
index 714e51e5be5bd2c7038f1965a74545a01c5a268c..55e2bf652beff53d6694e3cf20d2d2e4d6f17393 100644 (file)
 #define ACLKXE         BIT(5)
 #define TX_ASYNC       BIT(6)
 #define ACLKXPOL       BIT(7)
+#define ACLKXDIV_MASK  0x1f
 
 /*
  * DAVINCI_MCASP_ACLKRCTL_REG Receive Clock Control Register Bits
 #define 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
 #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
 #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);
index 0de9ed6ce038a8472aeb762d403fbf26d579bc24..0edd3b5a37fd86a5c04a54b66b8735d900e33a06 100644 (file)
 
 #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;
index 93ea3bf567e1fd1835ff643ff4e73d67fecdce12..afab81f844ae82c32418d6d1f83301c2d29d1f4e 100644 (file)
@@ -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);
                }
        }
index fc4d01cdd8c95c92b11694faece56d77fc648bd9..b6ef7039dd097b4ac99c6e9b14a0c35ed59fd203 100644 (file)
@@ -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 */
index 4563b28bd6254ddbeda6f0cd8229f22b10159ef7..3b98159d9645a8ecf917fb8c86c41de6a401c929 100644 (file)
@@ -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
index 5f3cf3f52ea03e16a1a374ca530f6daec7a2ed35..afd34794db539a0f5de4154a5a635a69f40913e1 100644 (file)
@@ -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
index 267d5b4b63ceb8392c9bd1433e2f1f6c288b92cf..75ffdf0e2aada7dc3a75d1d481014b8e7f94d160 100644 (file)
@@ -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);
 
index 6feb26500580749fc4b19b18368fdcd2d73175d0..9cc5c1f82f093f5b171877e1bd5e5672cf9c46cd 100644 (file)
@@ -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);
index 4ed2afd47782cba1667cf109d3c63c6d501ba2a1..7decbd9b234094945f58065962ba6a6cb22c0200 100644 (file)
@@ -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;
index 524ce6210ceea8588594664064d7e4283e02d59e..251f4d981e0c6e8882c6f0d9c23efad821e87e05 100644 (file)
@@ -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,
index 549b31fdc9dd4eabf268db09c5318e047e1a9646..4ae30f21fdb5385c003553e31c60bcaaa60d23cb 100644 (file)
@@ -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);
index d85929b79c350cad32be2ad46e2963cdc93249da..bf363d8d044aa2f1c38d44f0c66a20f1131a65de 100644 (file)
@@ -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);
index 9ffc9e66308f297a5e9a6ed39c7a3ddece48b9d2..5ec362ae4d012b654cdadbfeace42036ed76764e 100644 (file)
@@ -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);
index 93dc360b17770cbb2833afdc6fc7eb5c70c5b19a..d5cd9eff3b48e92ca77349b930fe84056fcd7017 100644 (file)
@@ -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");
index 199408ec42612dfe57f63e3933457e901cf7bcfa..424347e9b2d7d89df9e2db3a264c78c0a8113014 100644 (file)
@@ -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);
 
index dd566444e3c3b61b832a62e3763645393fcfbd88..3b480423747fc3d00f70978173a676736057c562 100644 (file)
@@ -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",
index a313c0ae36dba38f5bd0abbb002f5072c72ec259..a4aec0488dd325cd87f68db6a5705d9b1fcd312a 100644 (file)
@@ -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,
index ba1f0a66358f30288c6de2bf4fcba4e7468dd952..b95b966f25a06acbc97c6693c05e2560072884f3 100644 (file)
@@ -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,
index 9ff9318c52b9df42e7c8f61fb3aac2c3bba56983..228c52e71440dde17f0a41b4d0e34d9a260718d5 100644 (file)
@@ -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.
index 2b76877b1789479b0e7bfd1bd2a69640e298c77f..3d1074179057936faa402e90de0f8752822f60f4 100644 (file)
@@ -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);
index 144d496036370e84d888d71d33703e39370eff41..ba59c23a137b3e4e19b1f03047b93fcd5f376301 100644 (file)
@@ -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 (file)
index 0000000..f215519
--- /dev/null
@@ -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");
index 4b63ec8eb372ee917a06c314764a2d7f6804a892..8e52c1485df37bfdbe21cbbbc49e801663f4126c 100644 (file)
@@ -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,
index 41349670adab8ab18c00ef9bc696b2826e4fcf87..6cef491f4823cc28467216c8fe207b4eb7df271d 100644 (file)
@@ -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,
index 9b8cf256847d1ef8ace03ee8b0a94a1735a03eae..710059292318878886d00383396413c3ec87c8d1 100644 (file)
@@ -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,
index e8aaff18d7cc4c9b18ed2d178cc69c2ddc77a6cb..55fd6b5df55f5d988799b93ec64995fb4c06a038 100644 (file)
@@ -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);
index 2ba08148655f32ee2fa7301c44d65b54e7ea02fb..d3d4bdca1cc62d0387ca558cb7b7b020209b6f63 100644 (file)
 #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);
index 1d5db484d2df331b15e8e385cd32e2acd79e4d79..282d8b1163ba9583afd6e38e38400ce7efea29e9 100644 (file)
@@ -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,
index c28540aeea257d78091d0ea5739feeefed941ba7..b979c7154715a0ee9407c908f76f9f1ca9f91748 100644 (file)
@@ -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);
index c67bbc57498716534ba751765b46e60e9d08bf4d..1d0ed6f8add7ba5a7236f428476ab6f981522ab6 100644 (file)
@@ -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);
index f9084d83e6bd2ae178d562c2c243de4bb1fb6fcf..4d92637ddb3fd878f86e4d4525fbd024d94b2618 100644 (file)
 #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
 
 #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
index 2cc7782714b53830716fe74cea0c94c3527bc705..4139116c33b51f85bbc1794a885488f14811ec7e 100644 (file)
@@ -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);
index f82d766cbf9eb7ecd5ddd7cea788781d07b7af86..564b5b60319d7af26de86810515f7e9a276e93c0 100644 (file)
@@ -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);
 }
index c294fbb523fce2dac76a70d9e5537a47fee40042..365d9d27a3216b2c8969451c83b0e49e0bbc9520 100644 (file)
@@ -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",
index 215113b05f7d07c6ec46ecb591ec69bd04c5c610..b1d9b5ebeeeb77d5028a1bd183b4828e7737d78d 100644 (file)
@@ -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);
index 946020a647db2e1d5eec71f82fb9a3c936ced546..0418467a48489716475a3ff33cf8928b69d302c0 100644 (file)
@@ -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);
index 37585b47f4e3c4a5ea48ce7513ef08093de7e08d..c894ff0f25809c997197496e810cc52d0299d40a 100644 (file)
@@ -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);
index d8e96b2cd03ec201306ceaebf3962531f48f0cac..2600447fa74f823542f2668e216071d2240dfdf3 100644 (file)
@@ -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);
index afb8d4f1bedfac70eb98492ce5b4c023bb9d0752..285c8368cb47bcaf3461b4470f09fb9d7159c0fc 100644 (file)
@@ -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);
index 49a67259ce5a1d115de8bce006e2d6d99b48a633..f93e0b0af3035dbda43ccb0a87653fcf7131f7ac 100644 (file)
 
 #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 */
index a57a4e68dcc6166a2161b49b1d21ab7a8e49dc87..e7d93fa412a9c3387eef239300b44de4cac19dcb 100644 (file)
@@ -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);
index 5a6aeaf552a89666672e4bc2a46a3106ba26a532..ba49ccd9eed9149f234907c6efb66af5587328e6 100644 (file)
@@ -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);
index eaa2ea0e3f8115eb03bc864708f24a14f20b4d46..d4eaa92e518ec22af5c3751be13653dff5b268f9 100644 (file)
@@ -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);
index f59c69fb400ee60861bf334067aa1ee29df00d12..7ea24819d570ec912f60fc978497578bddeb753b 100644 (file)
@@ -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);
index a6ee157478593f1e5eb338e51597df176308a953..8d2defd6fdbe04375344a6f9fb440ceac935c347 100644 (file)
@@ -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);
index 56965bb3275ccd5c2fea1dc3fe143e3e3e7b622d..2fe8be20945278dc04cf23e22ef112abbf746383 100644 (file)
@@ -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);
index 52977aa303554d54113530805e421f450db68e33..47bdbd415ad87af59686327ad3be8f25c48bf2a4 100644 (file)
@@ -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);
index 3b97b87971f5462c3ea972ac6f92f5c25fc48106..4541d28b531495d7484f3a2dfcf4fe8472af451f 100644 (file)
@@ -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);
index 1ff6bb9ade5c98fd1ac644b0567f42f367d543d8..771bff27ac3e4809e3ae38d75c9d22b648375247 100644 (file)
@@ -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);
index 5e666e03d3331d39921a95bee2b5dc5e13c55230..4ad76099dd43fdec0d9e7262db77f1e07cd20713 100644 (file)
@@ -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);
index 863367ad89ce6aa1b173914f8c2541903d4f9846..f4cce1e8011242364807ebe21dc15b74acb1e3c7 100644 (file)
@@ -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);
index 7b1bc2390039ab324b5146daf63c5a72ec21411e..70d799b13f0d3fed2464c61046eb3e7439ebd8e4 100644 (file)
@@ -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);
index 47b89d71e287bc087640cdf064a7c4f6a92cdfea..f94d2ab51351b63932ff6e62d434cb08671dcc54 100644 (file)
@@ -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);
index ea9707ec6f28e706847e9991ee756747eac5309a..8768a640dd71953a0c78b43d0df539d0b5c6ad18 100644 (file)
@@ -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);
index 2a342c92d829563fbe3089bac84e486078ce8ef3..dcc9b04bd92c0575295e45455a59bf34dd419938 100644 (file)
@@ -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);
index b93dafd32b809e63dd8280441261cde86da9f9ab..eef1f7b7b38e27c9ffcfb1b340df0f66d3173275 100644 (file)
@@ -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);
index 8687c1c65d293dd932fc920880c4a889e0b19d97..97b711e12821e02c2b62c6ceb377fb4a942ee71f 100644 (file)
@@ -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,
index e834faf859fdcf91e5c1889b1975b2fff357e206..190eb0bccf5f1a9467cbccbec281d623e9a4065d 100644 (file)
@@ -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);
index 4d6cb8a30fc847643eddb4ac222de66b576e82bf..41c3a09b53eaab72824ffe36862407b18c56d32b 100644 (file)
@@ -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);
index aa3da91907c66f23f1fe895da2128ec379888d34..2074e2daf9c6a341e002ff26771e05de9ce2f9a6 100644 (file)
@@ -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,
index d2cc81735036ea8dd6a1aff7f61465caa29fd2fd..fafe46355c316b20df0f1e3fb114cae8d4cae9e2 100644 (file)
@@ -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);
index 4da5fc55c7ee81d81369fae163344e8058c96b86..d3eb0c2eec7724a843f277647cb80d5ed8ecea9f 100644 (file)
@@ -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);
index 06ea2744cc88f161e8d3508137747ee7d5958669..4b0a009bd68388e0355ff82841b7673d46120181 100644 (file)
@@ -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,
index 3075a426124cc119cfc43355c2403fba835ec4b4..6b1a06f67564abc2ce97450ed9cad05c1cd7a2ee 100644 (file)
@@ -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",
index fdd6bedef9bd7d818dadf36049df53ed067d842d..ecff116cb7b034484cd3c420ae483d576ef0db95 100644 (file)
@@ -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);
index 2aec63f3706acf826f8f9424fa496a1a479814ab..a3fe19123f07218bbd8af8bb7bd1cf6a26af8067 100644 (file)
@@ -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);
index 935491a8a7706f32e4d62e5cf9b50c66880168b1..f4ea4f6663a2c0d396997d7aef5cc1871f6ea6e5 100644 (file)
@@ -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);
index aaabdbaec19c6cf389f887669af54a3558f16aba..fee4d477a49cab75810ab7f02579a50516227450 100644 (file)
@@ -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,
index 716da861c629399de5e5322b1556c4e7ae46d08e..1358c7de2521b7c296aaf2b031f78cf662523c96 100644 (file)
@@ -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);
index 14fbcd30cae574dbc57b8f20eae191dc332c0f93..0df3c5644cfafb9629621b728339157cc8496cc7 100644 (file)
@@ -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,
index a2ca1567b9e4ff93a481d99065820d887ff8a72c..ceed466af9ff8f25b0007b8399cec68c87a06daa 100644 (file)
 #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)
 
  */
 #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",
@@ -269,6 +355,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,
@@ -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);
index b70964ea448cef264bf540597850558e7c9fd23c..db87628d7630cd0effc77588deb6f1fc7d337140 100644 (file)
@@ -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");
index 7d1ead77ef2121751269bb74ca80681033f5d00c..73d8c7c8a1e8458119d9c2b5afecece3b64bfe1a 100644 (file)
@@ -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
index c23c2ae91f58e441ae095ba30f7cbadcd9f1d000..d37ede58e0a8620eb21ba317a8885b7601d02c3b 100644 (file)
@@ -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,
index 6e3257717c54b24c49fa840e8696ccd169612d86..3870e9678b5d2a8a9d843d3f0766628df67bea48 100644 (file)
@@ -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,
        },
index 40b00a13dcd1b1c664636406ae693faa0bdf996f..d2d124f1dd1b2a3c83cdd9c51c104be78b4f18b9 100644 (file)
@@ -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,
index c227c3163caeacba809ce7fc0b0b0276062a5008..a07950b0c8ceba1756163c0d59b4c20b0ad7269e 100644 (file)
@@ -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);
index 1578663a1faa55de01e5d9110ef41dfe9963f4d4..b5f6abd9d2216d7f9664ca337468ff7792c93b0d 100644 (file)
@@ -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,
index ee52c8a007790972a62e9a84bdf196650a27e06b..bfb91f34a22a95f0a4c65084e085cc84a6db5349 100644 (file)
@@ -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);
index 69c4a5934a4d936c2dc48af9dcf980c987825ed2..9342fc270c2ba2ba62414ad388aaae1e92ad4660 100644 (file)
@@ -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",
 },
 };
 
index 6abf341c4a2ab3f4a224f1161770228dc07da93a..570cf522950824aca76801cce2184291b849821b 100644 (file)
@@ -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);
index 321d51134e47789a02c6d6483a0cb508a5b187c1..c7e965f80d2e41d46b7525cd21992ae8b7aec5d9 100644 (file)
@@ -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",
index c86081992dfd9331eeaed79c97f656705162b450..13bab79ad93d2fb493608b7fa0b909df42be26ac 100644 (file)
@@ -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,
index 21e12361a9cd137e1ae595a20c50210dcce9283a..a5826ea9cad63af16d20612155744c42c94320f0 100644 (file)
@@ -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,
        },
index ac7701b3c5dc01a95138b3c5c72ecfe25eeacce5..22133771639359877a7a918a593d28f9eac3fa9d 100644 (file)
@@ -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,
index 0aae3a3883dc4d348870a8db3aae43fc558065f7..ee10e8704e976f61f7ea6332416946af5471f59a 100644 (file)
@@ -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,
index 335a7d8a4a8d64b24cb6a8d50f31746d259ed094..2c015f62ead603564683c1920ec3613ad5df7768 100644 (file)
@@ -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);
 
index 7ace6a87f41b5e673a49f87f1e659be6ea11cd73..d8a0543cae5e8d19834f0c963a55d51a372d0dba 100644 (file)
@@ -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);
index c42d5f00b0e1cc2cdc75bfcd625bc02a35aa7825..1ac0d7a63a3a0053170825af55c78fd7e599f590 100644 (file)
@@ -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);
index d731042e51b07db12aff2adc6685d97f3af6e00e..333e1b7f06c799307d2f9d7b46fc14074bd04caa 100644 (file)
@@ -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 = {
index f2dcb424ea255056aa6f3dbe224d9f0bfe14dfe7..58ae3237ef6945c0f4e29f890ad5ddc8bd526fac 100644 (file)
@@ -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,
index 720ba29bb7e4174e0929a77490f55b7f72c88f09..c390aad68cfbcf729292d3797a9c3e0340fac4bd 100644 (file)
@@ -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",
 },
 };
 
index beaa9c15d6978c64f3899596a7239f829fddb63d..a2f2363fe1c29d136434121377ccb5d3f4363f71 100644 (file)
@@ -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",
index ade2809cf393eebc97d74952b44c65aaa35835ac..7e2b710763be05c96537214189612fae3c538aa9 100644 (file)
@@ -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,
        },
index fab5322e9f055002a3acb8a1d6b0bae06f457f38..e43bd4294f99ad26011744f0192a83aaad89f9c3 100644 (file)
@@ -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);
index 48dd4dd9ee08dc7f51c6e523e633f52e922307fb..b0d0ab8bff5ae8299628cd1aec8d229af4a73af6 100644 (file)
@@ -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);
index 77ecba9351193c0ad2a8e6c6951449192e7bf3d2..3688a32000a2bc752122958abdd4818cfb7d7046 100644 (file)
@@ -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);
index 55b2ca7f3290a624d1b63145eb5997eafa770e7e..0d20e4ed27aacd4bf4ce989ad0eada0a25191765 100644 (file)
@@ -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",
index bc24c7af02b2e23ff57342b1901841c879198fd1..5008e5bd6ed8072c62a0b9feb34f136497801b50 100644 (file)
@@ -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,
index c7e1c28528a4a6861593539a30afa1e41de30dd6..57df90d6b7c1bfdedbb5705fc0b2b0fef47d70d4 100644 (file)
@@ -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);
index 9199649bf78628db3bab47a61f1fb02ffa2e4902..f21ff608a8199dd09f70b19b0bf92070a86fd28f 100644 (file)
@@ -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);
index 7da20186b19e63bdf7efe6372a33b41190e82a2f..19eff8fc4fdddda4a8ca47972a8c9700c7ea0af1 100644 (file)
@@ -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);
index 9d7f30774a44d9524cb71f6697fc0ce96825295c..a606d0f93d1cea4db2e88f47e8ba0d94b36aa59f 100644 (file)
@@ -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 */
@@ -188,6 +189,14 @@ typedef int (*set_rate_func)(struct device *dev, int rate, int enable);
  *             --> go to codecs
  */
 
+/*
+ *     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);
 }
 
index 3474d7befe5ae537fc6e9862050f5e81dcce9daa..4cc2d64ef4765a68f458da65caedce29d8c86641 100644 (file)
@@ -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);
index 52d4c17b12325ac079ed8b0cb65950c382290344..34facdc9e4acfd68594e3db561b2aca108235459 100644 (file)
@@ -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);
index ff82b56a886093e43c5456b14592452478d5d4a2..c8e73a7039348e7818b15bacb95b1e6e6268b856 100644 (file)
@@ -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);
index 9d56f0218f41688576fec511db272e6484480bdb..e72f55428f0ba8ece44cdea8f6f720efc5c1d868 100644 (file)
@@ -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);
index 10d21be383f6d511221094a1fa3a9a3b9657a464..9c768bcb98a6460640577688b2f7f9d71d5a8106 100644 (file)
@@ -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;
                }
index 6e35bcae02df4b6a0e79709482a018f099615e21..1e36bc81e5af1fb015ffef62f628781910984bbb 100644 (file)
@@ -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,
index bbc125748a3843decc6ffd04d171fcf6f6b9fc5c..111b7d921e890c0051444b1a28fb6edfe78fd837 100644 (file)
@@ -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");
index 1ab5fe04bfccb066853fc664d9db9bea68a9f8ce..0bb5cccd77663a4d819a67731245e51564af3224 100644 (file)
@@ -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);
                }
index ef22d0bd9e9e62725f25f472aec279b75cf56e64..5c3ca2a3466170cd132464760dffd9b63155ebe9 100644 (file)
@@ -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;
                }
        }
index 60053709e417b0bdcecc81d13ac676fc885021e7..fe4541df498cbd85eb4a10275a658ee15cdbab9b 100644 (file)
@@ -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;
index 8c7f23729446b1582f6d7625d5933aad905e45d7..9b76cc5a114897613ed3d19e87b13b649037c4be 100644 (file)
@@ -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);
index bf99296bce95bcb9cd78997709f8ed034da1dec0..654318483877e0094e071ba73c1a7fe7e7bc0681 100644 (file)
@@ -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,
index 0832e8afd73c9df70df50474d62e145b30eaa707..caa772de5a184cb021def3333323e4343343fc51 100644 (file)
@@ -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);
 
index 3ebc8670ba00f0bd4f0c901efefe50b433b309b0..04771d14d34342181932df8a5bccf07e19a5191b 100644 (file)
@@ -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);
index 64b67a3091964a655c19a6106aa671332cd2b89f..f354dc390a0be4c1b57ae473f8b357f9c66cb632 100644 (file)
@@ -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,
index 44184228d1f0acfbd3fe6c625da2bd832908608e..27e91dd0b91c7d9b8b69fcdfb18056cee31d1c96 100644 (file)
@@ -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);
 
index 76cb1b363b71c2ce2d1be75c27113c3cf2154127..c80adb9da472a7ee2d71eb0de13d6d171e5266e1 100644 (file)
@@ -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);
 
index e18733963cb4b00111ca03f3ad3aebb2ed910124..c925ab0adeb6b0a2750106518f825cfd7b1ef864 100644 (file)
@@ -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);
 }
index ea9166d5c4ebeba6c649e6fcb8551c290acc2849..c8ef88a67c59f56b201b2d41b10bc8b44512d510 100644 (file)
@@ -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);
 
index cee13b7bfb949ffacd8e8cdabccea8030ba8659a..bbd79bf563031f755f6ef267664814a9f10e3c0c 100644 (file)
@@ -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);
 
index e69a4f7000d6166e0a0065365827486fb4c5fc99..7fcf6c2297db290b2c946bcc2cc9347bd209cfc9 100644 (file)
@@ -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);
 
index 28db4ca997ca2b6c3f768de842ea84f567f4fd25..16ab69635e2e209da6913b58e700a8b2eec0c00d 100644 (file)
@@ -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,
index b609d2c64c555b0346b6c9cb7ade29cb95d6277f..45a6428cba8db9367d657a79320b13fb6b27bffb 100644 (file)
@@ -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);
index 54f7e25b6f7d479d30bed372ba5d12ce1abacb22..ae6990738783ad18c84cd2914119f90c7a2727dc 100644 (file)
@@ -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);
index be94bf9bf94f51b31b4ba5d1aaeeeabcc58ea043..94a3e5705aaa498495b16e0b50749b111e30f976 100644 (file)
@@ -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);
 
index 98202a34a5dd16d3626171620ee270c2051713a7..9c778d9c383804cf998f40ce212bd3b6915b0634 100644 (file)
@@ -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;
index 1a04e248453c6fb743b7fb765d1ad1eeaa55cd39..846fa82a58d013bbb04980fdfeab9aa44d4e505d 100644 (file)
@@ -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);
index 77ed44d371e994a244d1393f0898fbae8a7af764..76d344476afc398d6cca59943eb065b195ce734d 100644 (file)
@@ -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
index 5701787c0e6bce406603ebb8590668d853900fd6..174d21fb56e2e326246231b30ce589a90919a9ff 100644 (file)
@@ -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;
index f2eabd3f22fdde3453541b8a72a89da623e3d2ff..54aaad2a10f53aa87a42fb01a1e74491ec01b9b2 100644 (file)
@@ -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);
index ae35f5342e105dc3700e5589da6d23a4f4a6ab63..75e6016d3efe79e0b025115f2f0148a9e3403aa3 100644 (file)
@@ -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);
index c6500d00053b21314086f9d88f8dcd72e91e4cc7..4dd60d8a4889bbd82bae4cfee9bd23be2ea5a4a7 100644 (file)
@@ -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);
index fc8cc823e4388ad15929d9b65f1fb065172fa2de..4394ae796356c2c46cce90e9e5e20707e85de06d 100644 (file)
@@ -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;
index 6c3d531a250efdc265acaf6bced48ab82aa32d05..9e6e3ffd86bbbc4212e72eb3d0c7cd69e6d44c8e 100644 (file)
@@ -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);
index d2af0a5ddcf355995087c1e111a0b447b412b6a4..6a0840b0dcff2be78366119126e5842aa4ab325f 100644 (file)
@@ -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 */
index 07ed914d5e71a3c165287e88f2381fac98614726..f6434c245720416f7fae946e62979a43f4b66333 100644 (file)
@@ -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;
index 9a596d95474a997afbf4c5e2bdaa5534c061fa19..5a40ba1434897d73cc1777d144e5d3cb4f02c587 100644 (file)
@@ -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 */
index 008569895381ff2b6c444a7ff9b1ad73a86b0a70..c109c4f75aba5a15fcbfbf2fc8998183a0112327 100644 (file)
@@ -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 */
 
index f0e5179b242bd48ce3c17314b96b3e27fdf5c85b..26722423330dd283b62d3fd4c5b77409913372cb 100644 (file)
@@ -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),
index 5114eccc1d8ee972222ca57e8738cdfde450ec48..c321006e5430ac763e593ecee6314c6cee8fd2d6 100644 (file)
@@ -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 */
index c97d05f0e966e95b8fdc3d0778e509e360c127c1..e2ca12fe92e946f662d47ae39983e176f7a50402 100644 (file)
@@ -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;
index 3104301b257df032a5047b3ea0dad5d4b7d43d3e..9b01133ee3fe9c22d3f51557430f011846e5bc8a 100644 (file)
@@ -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 */
index ff77b28f3da167fe0dd0788bfc110b52964c4b6f..225dfd737265411bead537f7f839b75863432e51 100644 (file)
@@ -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
index 00e5d0a469e1b065a6bee10b57d9fc1c41f2d716..adb8d03267a075eecf0bdd36421c5d7534cad978 100644 (file)
@@ -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;
 
index 7da0d0aa72cb1b31b88865371c9584e13fbd54e4..c828f8189c258294b0b2a681487360ea22f6e150 100644 (file)
@@ -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;
index dbf7999d18b4e7b300c0063f73aadf5dfa3f0f95..ccf95cfe186f324a7a7b95dc4c71e118df063706 100644 (file)
@@ -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),
index 814cb357ff88235dd87f37425985602867e3f5d5..8a751b4887ea87043fb34483a652f0d444145d5a 100644 (file)
@@ -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 */
index 34de6f2faf6120b492eb65208b9c9805aafe44e3..21049b882ee6445d47714074fddbcb550cf5eef8 100644 (file)
@@ -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;
                }
index 3d4c9705041ff5074c609dd2bfb303781a523c4e..447902dd8a4a8e5ef6338d274b260c9cd41b5403 100644 (file)
@@ -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);
index ddfef57c4c9fbe93c9551de6af2959051bba4c21..e831ee4238bbd79b2761c942dd900d2623f0912d 100644 (file)
@@ -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;
index eeefbce3873c11dc35a6e174c4ace79daeeaa8c1..34b9bb7fe87c8eabed83df8b7b77f510bedbc2b1 100644 (file)
@@ -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;
 }
 
index 298070e8f2d4e354da19dbca3e3d704a7b799321..ed4d89c8b52a52e6425ce5c992cc5d324b339d35 100644 (file)
@@ -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 :)
index a7f3d45a8acf1f6255a86f88038ca64012069137..aab80df201bdde8f6015d9b2451abb0c24efddb7 100644 (file)
@@ -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;
index ae2b7143522097bffd2a6060721d4f3db6b8000e..0422b1360af3a896da708a79365e3370be771fd8 100644 (file)
@@ -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;
 
index ef6fa24fc473b08a89dd33ef8158f004185f54cb..c6593101c049b88ca6e5661f8765b3f3df0b4d33 100644 (file)
@@ -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)) {
@@ -437,6 +453,103 @@ add_sync_ep:
        return 0;
 }
 
+/*
+ * 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
  *
@@ -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:
index 88d8cebbb244ade66eb43db91be9d9b5cf9669d5..49f9af995d7af3cf6fda51ef8d76102e8e40177a 100644 (file)
@@ -1456,6 +1456,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),
@@ -2162,6 +2196,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) {
@@ -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,
index 0f58b4b6d7023d0e4c47734216e276132c2fbe80..007fcecdf5cd1fa9536a24d6cac9059071393c69 100644 (file)
@@ -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 ||
index 1de0c8c002a8a2d35bc80e7de9a9c764a5945fc2..ad181d538bd9658edd79fec07d2fae125c9ebd38 100644 (file)
@@ -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;
                }
index ef42797f56fb56adf950eef3b764c5533263a8d9..1ac3fd9cc5a625e89cc1290ab3274ebac6982793 100644 (file)
@@ -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 */
 };
index f93b776370b6f31fc52d68fe9b3dbf8085d34ed3..3179c711bd65e159ed5a043c42dfa43fa3333f41 100644 (file)
@@ -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;
index b38a1f9ad4606db6e8544ee5908789eaae0ac0f0..938e8904f64d100ab082a4f1fcca0e68f05592f7 100644 (file)
@@ -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.
index e626fa553c5ae1b2db0f044fe0c987e13e5af9ec..6d25dcd2e97a9015da4c927c36b13d3763dc5827 100644 (file)
@@ -232,7 +232,7 @@ const struct option longopts[] = {
        }
 };
 
-static void help()
+static void help(void)
 {
        fprintf(stderr, "Usage: virtio_test [--help]"
                " [--no-indirect]"
index aca6edcbbc6fa09113389e87b3e76a55a871da98..af8c925e93ebd4536e41897c5fcfff10f3fffda8 100644 (file)
@@ -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];